diff --git a/lib/diaspora_federation/federation/receiver/slap_receiver.rb b/lib/diaspora_federation/federation/receiver/slap_receiver.rb
index 76cdb38..c036a74 100644
--- a/lib/diaspora_federation/federation/receiver/slap_receiver.rb
+++ b/lib/diaspora_federation/federation/receiver/slap_receiver.rb
@@ -14,10 +14,7 @@ module DiasporaFederation
# Parse the salmon xml
def parse
- sender_id = slap.author_id
- public_key = DiasporaFederation.callbacks.trigger(:fetch_public_key_by_diaspora_id, sender_id)
- raise Salmon::SenderKeyNotFound if public_key.nil?
- slap.entity(public_key)
+ slap.entity
end
end
end
diff --git a/lib/diaspora_federation/salmon/magic_envelope.rb b/lib/diaspora_federation/salmon/magic_envelope.rb
index 8dfcbb5..08b8474 100644
--- a/lib/diaspora_federation/salmon/magic_envelope.rb
+++ b/lib/diaspora_federation/salmon/magic_envelope.rb
@@ -99,7 +99,7 @@ module DiasporaFederation
# @see AES#decrypt
#
# @param [Nokogiri::XML::Element] magic_env XML root node of a magic envelope
- # @param [OpenSSL::PKey::RSA] rsa_pubkey public key to verify the signature
+ # @param [String] sender diaspora-ID of the sender or nil
# @param [Hash] cipher_params hash containing the key and iv for
# AES-decrypting previously encrypted data. E.g.: { iv: "...", key: "..." }
#
@@ -110,11 +110,11 @@ module DiasporaFederation
# @raise [InvalidSignature] if the signature can't be verified
# @raise [InvalidEncoding] if the data is wrongly encoded
# @raise [InvalidAlgorithm] if the algorithm used doesn't match
- def self.unenvelop(magic_env, rsa_pubkey=nil, cipher_params=nil)
+ def self.unenvelop(magic_env, sender=nil, cipher_params=nil)
raise ArgumentError unless magic_env.instance_of?(Nokogiri::XML::Element)
raise InvalidEnvelope unless envelope_valid?(magic_env)
- raise InvalidSignature unless signature_valid?(magic_env, rsa_pubkey)
+ raise InvalidSignature unless signature_valid?(magic_env, sender)
raise InvalidEncoding unless encoding_valid?(magic_env)
raise InvalidAlgorithm unless algorithm_valid?(magic_env)
@@ -162,15 +162,18 @@ module DiasporaFederation
private_class_method :envelope_valid?
# @param [Nokogiri::XML::Element] env magic envelope XML
- # @param [OpenSSL::PKey::RSA] pubkey public key or nil
+ # @param [String] sender diaspora-ID of the sender or nil
# @return [Boolean]
- def self.signature_valid?(env, pubkey)
+ def self.signature_valid?(env, sender)
+ sender ||= sender(env)
+
subject = sig_subject([Base64.urlsafe_decode64(env.at_xpath("me:data").content),
env.at_xpath("me:data")["type"],
env.at_xpath("me:encoding").content,
env.at_xpath("me:alg").content])
- sender_key = pubkey || sender_key(env)
+ sender_key = DiasporaFederation.callbacks.trigger(:fetch_public_key_by_diaspora_id, sender)
+ raise SenderKeyNotFound unless sender_key
sig = Base64.urlsafe_decode64(env.at_xpath("me:sig").content)
sender_key.verify(DIGEST, sig, subject)
@@ -179,17 +182,13 @@ module DiasporaFederation
# reads the +key_id+ from the magic envelope
# @param [Nokogiri::XML::Element] env magic envelope XML
- # @return [OpenSSL::PKey::RSA] sender public key
- def self.sender_key(env)
+ # @return [String] diaspora-ID of the sender
+ def self.sender(env)
key_id = env.at_xpath("me:sig")["key_id"]
raise InvalidEnvelope, "no key_id" unless key_id # TODO: move to `envelope_valid?`
- sender = Base64.urlsafe_decode64(key_id)
-
- sender_key = DiasporaFederation.callbacks.trigger(:fetch_public_key_by_diaspora_id, sender)
- raise SenderKeyNotFound unless sender_key
- sender_key
+ Base64.urlsafe_decode64(key_id)
end
- private_class_method :sender_key
+ private_class_method :sender
# constructs the signature subject.
# the given array should consist of the data, data_type (mimetype), encoding
diff --git a/lib/diaspora_federation/salmon/slap.rb b/lib/diaspora_federation/salmon/slap.rb
index f6c0b65..800feb1 100644
--- a/lib/diaspora_federation/salmon/slap.rb
+++ b/lib/diaspora_federation/salmon/slap.rb
@@ -46,12 +46,10 @@ module DiasporaFederation
#
# @see MagicEnvelope.unenvelop
#
- # @param [OpenSSL::PKey::RSA] pubkey public key for validating the signature
# @return [Entity] entity instance from the XML
# @raise [ArgumentError] if the public key is of the wrong type
- def entity(pubkey)
- raise ArgumentError unless pubkey.instance_of?(OpenSSL::PKey::RSA)
- MagicEnvelope.unenvelop(@magic_envelope, pubkey, @cipher_params)
+ def entity
+ MagicEnvelope.unenvelop(@magic_envelope, author_id, @cipher_params)
end
# Parses an unencrypted Salmon XML string and returns a new instance of
diff --git a/spec/lib/diaspora_federation/salmon/magic_envelope_spec.rb b/spec/lib/diaspora_federation/salmon/magic_envelope_spec.rb
index c967ce7..36ea707 100644
--- a/spec/lib/diaspora_federation/salmon/magic_envelope_spec.rb
+++ b/spec/lib/diaspora_federation/salmon/magic_envelope_spec.rb
@@ -104,6 +104,12 @@ module DiasporaFederation
describe ".unenvelop" do
context "sanity" do
+ before do
+ allow(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :fetch_public_key_by_diaspora_id, sender
+ ).and_return(privkey.public_key)
+ end
+
def re_sign(env, key)
new_sig = Base64.urlsafe_encode64(key.sign(OpenSSL::Digest::SHA256.new, sig_subj(env)))
env.at_xpath("me:sig").content = new_sig
@@ -111,7 +117,7 @@ module DiasporaFederation
it "works with sane input" do
expect {
- Salmon::MagicEnvelope.unenvelop(envelope.envelop(privkey), privkey.public_key)
+ Salmon::MagicEnvelope.unenvelop(envelope.envelop(privkey), sender)
}.not_to raise_error
end
@@ -125,14 +131,20 @@ module DiasporaFederation
it "verifies the envelope structure" do
expect {
- Salmon::MagicEnvelope.unenvelop(Nokogiri::XML::Document.parse("").root, privkey.public_key)
+ Salmon::MagicEnvelope.unenvelop(Nokogiri::XML::Document.parse("").root, sender)
}.to raise_error Salmon::InvalidEnvelope
end
it "verifies the signature" do
+ other_sender = FactoryGirl.generate(:diaspora_id)
other_key = OpenSSL::PKey::RSA.generate(512)
+
+ expect(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :fetch_public_key_by_diaspora_id, other_sender
+ ).and_return(other_key)
+
expect {
- Salmon::MagicEnvelope.unenvelop(envelope.envelop(privkey), other_key.public_key)
+ Salmon::MagicEnvelope.unenvelop(envelope.envelop(privkey), other_sender)
}.to raise_error Salmon::InvalidSignature
end
@@ -141,7 +153,7 @@ module DiasporaFederation
bad_env.at_xpath("me:encoding").content = "invalid_enc"
re_sign(bad_env, privkey)
expect {
- Salmon::MagicEnvelope.unenvelop(bad_env, privkey.public_key)
+ Salmon::MagicEnvelope.unenvelop(bad_env, sender)
}.to raise_error Salmon::InvalidEncoding
end
@@ -150,23 +162,31 @@ module DiasporaFederation
bad_env.at_xpath("me:alg").content = "invalid_alg"
re_sign(bad_env, privkey)
expect {
- Salmon::MagicEnvelope.unenvelop(bad_env, privkey.public_key)
+ Salmon::MagicEnvelope.unenvelop(bad_env, sender)
}.to raise_error Salmon::InvalidAlgorithm
end
end
it "returns the original entity" do
- entity = Salmon::MagicEnvelope.unenvelop(envelope.envelop(privkey), privkey.public_key)
+ allow(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :fetch_public_key_by_diaspora_id, sender
+ ).and_return(privkey.public_key)
+
+ entity = Salmon::MagicEnvelope.unenvelop(envelope.envelop(privkey), sender)
expect(entity).to be_an_instance_of Entities::TestEntity
expect(entity.test).to eq("asdf")
end
it "decrypts on the fly, when cipher params are present" do
+ allow(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :fetch_public_key_by_diaspora_id, sender
+ ).and_return(privkey.public_key)
+
params = envelope.encrypt!
env_xml = envelope.envelop(privkey)
- entity = Salmon::MagicEnvelope.unenvelop(env_xml, privkey.public_key, params)
+ entity = Salmon::MagicEnvelope.unenvelop(env_xml, sender, params)
expect(entity).to be_an_instance_of Entities::TestEntity
expect(entity.test).to eq("asdf")
end
diff --git a/spec/support/shared_slap_specs.rb b/spec/support/shared_slap_specs.rb
index ca8d526..da15993 100644
--- a/spec/support/shared_slap_specs.rb
+++ b/spec/support/shared_slap_specs.rb
@@ -4,18 +4,12 @@ shared_examples "a Slap instance" do
end
context "#entity" do
- it "requires the pubkey for the first time (to verify the signature)" do
- expect { subject.entity }.to raise_error ArgumentError
- end
-
- it "works when the pubkey is given" do
- expect {
- subject.entity(privkey.public_key)
- }.not_to raise_error
- end
-
it "returns the entity" do
- entity = subject.entity(privkey.public_key)
+ allow(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :fetch_public_key_by_diaspora_id, author_id
+ ).and_return(privkey.public_key)
+
+ entity = subject.entity
expect(entity).to be_an_instance_of DiasporaFederation::Entities::TestEntity
expect(entity.test).to eq("qwertzuiop")
end