add EncryptedMagicEnvelope
This is a simpler replacement for the EncryptedSlap
This commit is contained in:
parent
160da072b6
commit
744e194b90
3 changed files with 116 additions and 0 deletions
|
|
@ -13,5 +13,6 @@ require "diaspora_federation/salmon/aes"
|
||||||
require "diaspora_federation/salmon/exceptions"
|
require "diaspora_federation/salmon/exceptions"
|
||||||
require "diaspora_federation/salmon/xml_payload"
|
require "diaspora_federation/salmon/xml_payload"
|
||||||
require "diaspora_federation/salmon/magic_envelope"
|
require "diaspora_federation/salmon/magic_envelope"
|
||||||
|
require "diaspora_federation/salmon/encrypted_magic_envelope"
|
||||||
require "diaspora_federation/salmon/slap"
|
require "diaspora_federation/salmon/slap"
|
||||||
require "diaspora_federation/salmon/encrypted_slap"
|
require "diaspora_federation/salmon/encrypted_slap"
|
||||||
|
|
|
||||||
61
lib/diaspora_federation/salmon/encrypted_magic_envelope.rb
Normal file
61
lib/diaspora_federation/salmon/encrypted_magic_envelope.rb
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
module DiasporaFederation
|
||||||
|
module Salmon
|
||||||
|
# This is a simple crypt-wrapper for {MagicEnvelope}.
|
||||||
|
#
|
||||||
|
# The wrapper is JSON with the following structure:
|
||||||
|
#
|
||||||
|
# {
|
||||||
|
# "aes_key": "...",
|
||||||
|
# "encrypted_magic_envelope": "..."
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# +aes_key+ is encrypted using the recipients public key, and contains the AES
|
||||||
|
# +key+ and +iv+ as JSON:
|
||||||
|
#
|
||||||
|
# {
|
||||||
|
# "key": "...",
|
||||||
|
# "iv": "..."
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# +encrypted_magic_envelope+ is encrypted using the +key+ and +iv+ from +aes_key+.
|
||||||
|
# Once decrypted it contains the {MagicEnvelope} xml:
|
||||||
|
#
|
||||||
|
# <me:env>
|
||||||
|
# ...
|
||||||
|
# </me:env>
|
||||||
|
#
|
||||||
|
# All JSON-values (+aes_key+, +encrypted_magic_envelope+, +key+ and +iv+) are
|
||||||
|
# base64 encoded.
|
||||||
|
module EncryptedMagicEnvelope
|
||||||
|
# Generates a new random AES key and encrypts the {MagicEnvelope} with it.
|
||||||
|
# Then encrypts the AES key with the receivers public key.
|
||||||
|
# @param [Nokogiri::XML::Element] magic_env XML root node of a magic envelope
|
||||||
|
# @param [OpenSSL::PKey::RSA] pubkey recipient public_key
|
||||||
|
# @return [String] json string
|
||||||
|
def self.encrypt(magic_env, pubkey)
|
||||||
|
key = AES.generate_key_and_iv
|
||||||
|
encrypted_env = AES.encrypt(magic_env.to_xml, key[:key], key[:iv])
|
||||||
|
|
||||||
|
encoded_key = Hash[key.map {|k, v| [k, Base64.strict_encode64(v)] }]
|
||||||
|
encrypted_key = Base64.strict_encode64(pubkey.public_encrypt(JSON.generate(encoded_key)))
|
||||||
|
|
||||||
|
JSON.generate(aes_key: encrypted_key, encrypted_magic_envelope: encrypted_env)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decrypts the AES key with the private key of the receiver and decrypts the
|
||||||
|
# encrypted {MagicEnvelope} with it.
|
||||||
|
# @param [String] encrypted_env json string with aes_key and encrypted_magic_envelope
|
||||||
|
# @param [OpenSSL::PKey::RSA] privkey private key for decryption
|
||||||
|
# @return [Nokogiri::XML::Element] decrypted magic envelope xml
|
||||||
|
def self.decrypt(encrypted_env, privkey)
|
||||||
|
encrypted_json = JSON.parse(encrypted_env)
|
||||||
|
|
||||||
|
encoded_key = JSON.parse(privkey.private_decrypt(Base64.decode64(encrypted_json["aes_key"])))
|
||||||
|
key = Hash[encoded_key.map {|k, v| [k, Base64.decode64(v)] }]
|
||||||
|
|
||||||
|
xml = AES.decrypt(encrypted_json["encrypted_magic_envelope"], key["key"], key["iv"])
|
||||||
|
Nokogiri::XML::Document.parse(xml).root
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
module DiasporaFederation
|
||||||
|
describe Salmon::EncryptedMagicEnvelope do
|
||||||
|
let(:sender_id) { FactoryGirl.generate(:diaspora_id) }
|
||||||
|
let(:sender_key) { OpenSSL::PKey::RSA.generate(512) } # use small key for speedy specs
|
||||||
|
let(:entity) { Entities::TestEntity.new(test: "abcd") }
|
||||||
|
let(:magic_env) { Salmon::MagicEnvelope.new(entity).envelop(sender_key, sender_id) }
|
||||||
|
|
||||||
|
let(:privkey) { OpenSSL::PKey::RSA.generate(1024) } # use small key for speedy specs
|
||||||
|
|
||||||
|
describe ".encrypt" do
|
||||||
|
it "creates the json correctly" do
|
||||||
|
encrypted = Salmon::EncryptedMagicEnvelope.encrypt(magic_env, privkey.public_key)
|
||||||
|
|
||||||
|
expect(JSON.parse(encrypted)).to include("aes_key", "encrypted_magic_envelope")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "encrypts the aes_key correctly" do
|
||||||
|
encrypted = Salmon::EncryptedMagicEnvelope.encrypt(magic_env, privkey.public_key)
|
||||||
|
|
||||||
|
json = JSON.parse(encrypted)
|
||||||
|
aes_key = JSON.parse(privkey.private_decrypt(Base64.decode64(json["aes_key"])))
|
||||||
|
|
||||||
|
expect(aes_key).to include("key", "iv")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "encrypts the magic_envelope correctly" do
|
||||||
|
encrypted = Salmon::EncryptedMagicEnvelope.encrypt(magic_env, privkey.public_key)
|
||||||
|
|
||||||
|
json = JSON.parse(encrypted)
|
||||||
|
aes_key = JSON.parse(privkey.private_decrypt(Base64.decode64(json["aes_key"])))
|
||||||
|
key = Hash[aes_key.map {|k, v| [k, Base64.decode64(v)] }]
|
||||||
|
|
||||||
|
xml = Salmon::AES.decrypt(json["encrypted_magic_envelope"], key["key"], key["iv"])
|
||||||
|
|
||||||
|
expect(Nokogiri::XML::Document.parse(xml).root.to_xml).to eq(magic_env.to_xml)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".decrypt" do
|
||||||
|
let(:encrypted_env) { Salmon::EncryptedMagicEnvelope.encrypt(magic_env, privkey.public_key) }
|
||||||
|
|
||||||
|
it "returns the magic envelope xml" do
|
||||||
|
decrypted = Salmon::EncryptedMagicEnvelope.decrypt(encrypted_env, privkey)
|
||||||
|
|
||||||
|
expect(decrypted.name).to eq("env")
|
||||||
|
|
||||||
|
expect(decrypted.xpath("me:data")).to have(1).item
|
||||||
|
expect(decrypted.xpath("me:encoding")).to have(1).item
|
||||||
|
expect(decrypted.xpath("me:alg")).to have(1).item
|
||||||
|
expect(decrypted.xpath("me:sig")).to have(1).item
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Reference in a new issue