Class: DiasporaFederation::Salmon::MagicEnvelope
- Inherits:
-
Object
- Object
- DiasporaFederation::Salmon::MagicEnvelope
- Includes:
- Logging
- Defined in:
- lib/diaspora_federation/salmon/magic_envelope.rb
Overview
Represents a Magic Envelope for diaspora* federation messages
When generating a Magic Envelope, an instance of this class is created and the contents are specified on initialization. Optionally, the payload can be encrypted (#encrypt!), before the XML is returned (#envelop).
The generated XML appears like so:
<me:env>
<me:data type="application/xml">{data}</me:data>
<me:encoding>base64url</me:encoding>
<me:alg>RSA-SHA256</me:alg>
<me:sig key_id="{sender}">{signature}</me:sig>
</me:env>
When parsing the XML of an incoming Magic Envelope MagicEnvelope.unenvelop is used.
Constant Summary collapse
- ENCODING =
Encoding used for the payload data
"base64url".freeze
- ALGORITHM =
Algorithm used for signing the payload data
"RSA-SHA256".freeze
- DATA_TYPE =
Mime type describing the payload data
"application/xml".freeze
- DIGEST =
Digest instance used for signing
OpenSSL::Digest::SHA256.new
- XMLNS =
XML namespace url
"http://salmon-protocol.org/ns/magic-env".freeze
Instance Attribute Summary collapse
-
#payload ⇒ Entity
readonly
The payload entity of the magic envelope.
-
#sender ⇒ String
readonly
The sender of the magic envelope.
Class Method Summary collapse
-
.unenvelop(magic_env, sender = nil, cipher_params = nil) ⇒ Entity
Extracts the entity encoded in the magic envelope data, if the signature is valid.
Instance Method Summary collapse
-
#encrypt! ⇒ Hash
Encrypts the payload with a new, random AES cipher and returns the cipher params that were used.
- #envelop(privkey) ⇒ Nokogiri::XML::Element
-
#initialize(payload, sender = nil) ⇒ MagicEnvelope
constructor
Creates a new instance of MagicEnvelope.
Methods included from Logging
Constructor Details
#initialize(payload, sender = nil) ⇒ MagicEnvelope
Creates a new instance of MagicEnvelope.
54 55 56 57 58 59 |
# File 'lib/diaspora_federation/salmon/magic_envelope.rb', line 54 def initialize(payload, sender=nil) raise ArgumentError unless payload.is_a?(Entity) @payload = payload @sender = sender end |
Instance Attribute Details
#payload ⇒ Entity (readonly)
The payload entity of the magic envelope
43 44 45 |
# File 'lib/diaspora_federation/salmon/magic_envelope.rb', line 43 def payload @payload end |
#sender ⇒ String (readonly)
The sender of the magic envelope
47 48 49 |
# File 'lib/diaspora_federation/salmon/magic_envelope.rb', line 47 def sender @sender end |
Class Method Details
.unenvelop(magic_env, sender = nil, cipher_params = nil) ⇒ Entity
Extracts the entity encoded in the magic envelope data, if the signature is valid. If cipher_params
is given, also attempts to decrypt the payload first.
Does some sanity checking to avoid bad surprises…
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/diaspora_federation/salmon/magic_envelope.rb', line 116 def self.unenvelop(magic_env, sender=nil, cipher_params=nil) raise ArgumentError unless magic_env.instance_of?(Nokogiri::XML::Element) validate_envelope(magic_env) validate_type(magic_env) validate_encoding(magic_env) validate_algorithm(magic_env) sender ||= sender(magic_env) raise InvalidSignature unless signature_valid?(magic_env, sender) data = read_and_decrypt_data(magic_env, cipher_params) logger.debug "unenvelop message from #{sender}:\n#{data}" new(XmlPayload.unpack(Nokogiri::XML::Document.parse(data).root), sender) end |
Instance Method Details
#encrypt! ⇒ Hash
Encrypts the payload with a new, random AES cipher and returns the cipher params that were used.
This must happen after the MagicEnvelope instance was created and before #envelop is called.
89 90 91 92 93 |
# File 'lib/diaspora_federation/salmon/magic_envelope.rb', line 89 def encrypt! AES.generate_key_and_iv.tap do |key| @payload_data = AES.encrypt(payload_data, key[:key], key[:iv]) end end |
#envelop(privkey) ⇒ Nokogiri::XML::Element
66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/diaspora_federation/salmon/magic_envelope.rb', line 66 def envelop(privkey) raise ArgumentError unless privkey.instance_of?(OpenSSL::PKey::RSA) build_xml {|xml| xml["me"].env("xmlns:me" => XMLNS) { xml["me"].data(Base64.urlsafe_encode64(payload_data), type: DATA_TYPE) xml["me"].encoding(ENCODING) xml["me"].alg(ALGORITHM) xml["me"].sig(Base64.urlsafe_encode64(sign(privkey)), key_id) } } end |