read sender from magic envelope and fetch key
This commit is contained in:
parent
d2cdbd2aff
commit
76a4ea929b
3 changed files with 56 additions and 5 deletions
|
|
@ -20,6 +20,10 @@ module DiasporaFederation
|
||||||
class InvalidHeader < RuntimeError
|
class InvalidHeader < RuntimeError
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Raised, if failed to fetch the public key of the sender of the received message
|
||||||
|
class SenderKeyNotFound < RuntimeError
|
||||||
|
end
|
||||||
|
|
||||||
# Raised, if the Magic Envelope XML structure is malformed.
|
# Raised, if the Magic Envelope XML structure is malformed.
|
||||||
class InvalidEnvelope < RuntimeError
|
class InvalidEnvelope < RuntimeError
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -101,9 +101,8 @@ module DiasporaFederation
|
||||||
# @raise [InvalidSignature] if the signature can't be verified
|
# @raise [InvalidSignature] if the signature can't be verified
|
||||||
# @raise [InvalidEncoding] if the data is wrongly encoded
|
# @raise [InvalidEncoding] if the data is wrongly encoded
|
||||||
# @raise [InvalidAlgorithm] if the algorithm used doesn't match
|
# @raise [InvalidAlgorithm] if the algorithm used doesn't match
|
||||||
def self.unenvelop(magic_env, rsa_pubkey, cipher_params=nil)
|
def self.unenvelop(magic_env, rsa_pubkey=nil, cipher_params=nil)
|
||||||
raise ArgumentError unless magic_env.instance_of?(Nokogiri::XML::Element) &&
|
raise ArgumentError unless magic_env.instance_of?(Nokogiri::XML::Element)
|
||||||
rsa_pubkey.instance_of?(OpenSSL::PKey::RSA)
|
|
||||||
|
|
||||||
raise InvalidEnvelope unless envelope_valid?(magic_env)
|
raise InvalidEnvelope unless envelope_valid?(magic_env)
|
||||||
raise InvalidSignature unless signature_valid?(magic_env, rsa_pubkey)
|
raise InvalidSignature unless signature_valid?(magic_env, rsa_pubkey)
|
||||||
|
|
@ -148,7 +147,7 @@ module DiasporaFederation
|
||||||
private_class_method :envelope_valid?
|
private_class_method :envelope_valid?
|
||||||
|
|
||||||
# @param [Nokogiri::XML::Element] env magic envelope XML
|
# @param [Nokogiri::XML::Element] env magic envelope XML
|
||||||
# @param [OpenSSL::PKey::RSA] pubkey public key
|
# @param [OpenSSL::PKey::RSA] pubkey public key or nil
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
def self.signature_valid?(env, pubkey)
|
def self.signature_valid?(env, pubkey)
|
||||||
subject = sig_subject([Base64.urlsafe_decode64(env.at_xpath("me:data").content),
|
subject = sig_subject([Base64.urlsafe_decode64(env.at_xpath("me:data").content),
|
||||||
|
|
@ -156,11 +155,27 @@ module DiasporaFederation
|
||||||
env.at_xpath("me:encoding").content,
|
env.at_xpath("me:encoding").content,
|
||||||
env.at_xpath("me:alg").content])
|
env.at_xpath("me:alg").content])
|
||||||
|
|
||||||
|
sender_key = pubkey || sender_key(env)
|
||||||
|
|
||||||
sig = Base64.urlsafe_decode64(env.at_xpath("me:sig").content)
|
sig = Base64.urlsafe_decode64(env.at_xpath("me:sig").content)
|
||||||
pubkey.verify(DIGEST, sig, subject)
|
sender_key.verify(DIGEST, sig, subject)
|
||||||
end
|
end
|
||||||
private_class_method :signature_valid?
|
private_class_method :signature_valid?
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
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
|
||||||
|
end
|
||||||
|
private_class_method :sender_key
|
||||||
|
|
||||||
# constructs the signature subject.
|
# constructs the signature subject.
|
||||||
# the given array should consist of the data, data_type (mimetype), encoding
|
# the given array should consist of the data, data_type (mimetype), encoding
|
||||||
# and the algorithm
|
# and the algorithm
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,38 @@ module DiasporaFederation
|
||||||
expect(entity).to be_an_instance_of Entities::TestEntity
|
expect(entity).to be_an_instance_of Entities::TestEntity
|
||||||
expect(entity.test).to eq("asdf")
|
expect(entity.test).to eq("asdf")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "use key_id from magic envelope" do
|
||||||
|
it "returns the original entity" do
|
||||||
|
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
||||||
|
:fetch_public_key_by_diaspora_id, sender_id
|
||||||
|
).and_return(privkey.public_key)
|
||||||
|
|
||||||
|
entity = Salmon::MagicEnvelope.unenvelop(envelope.envelop(privkey, sender_id))
|
||||||
|
expect(entity).to be_an_instance_of Entities::TestEntity
|
||||||
|
expect(entity.test).to eq("asdf")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises if the magic envelope has no key_id" do
|
||||||
|
bad_env = envelope.envelop(privkey, sender_id)
|
||||||
|
|
||||||
|
bad_env.at_xpath("me:sig").attributes["key_id"].remove
|
||||||
|
|
||||||
|
expect {
|
||||||
|
Salmon::MagicEnvelope.unenvelop(bad_env)
|
||||||
|
}.to raise_error Salmon::InvalidEnvelope
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises if the sender key is not found" do
|
||||||
|
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
||||||
|
:fetch_public_key_by_diaspora_id, sender_id
|
||||||
|
).and_return(nil)
|
||||||
|
|
||||||
|
expect {
|
||||||
|
Salmon::MagicEnvelope.unenvelop(envelope.envelop(privkey, sender_id))
|
||||||
|
}.to raise_error Salmon::SenderKeyNotFound
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue