Nuntius:

A messenger, reporter, courier, bearer of news or tidings

Nuntius is a simple scheme to send and receive messages in a cryptographicaly secure and compatible way.

Usage

Encript a Message

  require 'nuntius'

  sender = Nuntius::Key.new( File.read('private_key_path') )
  messenger = Nuntius::Mesenger.new({
    :key => sender
  })

  receiver = Nuntius::Key.new( File.read('public_key_path') )

  envelope = messenger.wrap({
    :message => "Message Content",
    :to => receiver
  })

  envelope.data
    # => The encripted message
  envelope.key
    # => The encripted message key
  envelope.signature
    # => The encripted message signature

Decript a message

  require 'nuntius'

  receiver = Nuntius::Key.new( File.read('private_key_path') )
  messenger = Nuntius::Mesenger.new({
    :key => receiver
  })

  sender = Nuntius::Key.new( File.read('public_key_path') )

  envelope = Nuntius::Envelope.new({
    :data => 'The encripted message'
    :key => 'The encripted message key'
    :signature => 'The encripted message signature'
  })

  message = messenger.unwrap({
    :envelope => envelope,
    :from => sender
  })

  message
    # => The verified and decripted raw message

Encription Scheme

Under the hood Nuntius is just a wrapper around OpenSSL and by default uses RSA, AES in CBC mode and SHA512 to encript/decript and sign/verify the messages and URL Safe Base64 to encode/decode the results.

The whole scheme can be sumarized in 4 steps:

  • The message is encripted using AES-256-CBC with a randomly generated key.
  • The key is then encrypted using the receiver's public RSA key.
  • The encripted message's digest is calculated using SHA512 and then signed using the sender's private RSA key.
  • Finally the encripted message, the encripted key and the signed digest are encoded using the RFC4648 URL Safe Base 64 encoding

In other terms, encrypting a message with nuntius is the same as doing

  require 'openssl'

  sender = OpenSSL::PKey::RSA.new( File.read('sender_private_key') )
  receiver = OpenSSL::PKey::RSA.new( File.read('receiver_public_key') )

  cipher = OpenSSL::Cipher.new("AES-256-CBC").encrypt

  key = receiver.public_encrypt( cipher.random_key )

  data = cipher.update("message") + cipher.final

  signature = receiver.private_encrypt( OpenSSL::Digest::SHA512.new(data).digest )

  result = {
    :data => [data].pack("m0").tr("+/","-_").gsub("=","")
    :key => [key].pack("m0").tr("+/","-_").gsub("=","")
    :signature => [signature].pack("m0").tr("+/","-_").gsub("=","")
  }