From 00840f4f2edb8d1d46638ccbc90a1f4462d0867a Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 26 Aug 2017 13:47:38 +0200 Subject: Add handling of Linked Data Signatures in payloads (#4687) * Add handling of Linked Data Signatures in payloads * Add a way to sign JSON, fix canonicalization of signature options * Fix signatureValue encoding, send out signed JSON when distributing * Add missing security context --- app/lib/activitypub/linked_data_signature.rb | 56 ++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 app/lib/activitypub/linked_data_signature.rb (limited to 'app/lib/activitypub/linked_data_signature.rb') diff --git a/app/lib/activitypub/linked_data_signature.rb b/app/lib/activitypub/linked_data_signature.rb new file mode 100644 index 000000000..7173aed19 --- /dev/null +++ b/app/lib/activitypub/linked_data_signature.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +class ActivityPub::LinkedDataSignature + include JsonLdHelper + + CONTEXT = 'https://w3id.org/identity/v1' + + def initialize(json) + @json = json + end + + def verify_account! + return unless @json['signature'].is_a?(Hash) + + type = @json['signature']['type'] + creator_uri = @json['signature']['creator'] + signature = @json['signature']['signatureValue'] + + return unless type == 'RsaSignature2017' + + creator = ActivityPub::TagManager.instance.uri_to_resource(creator_uri, Account) + creator ||= ActivityPub::FetchRemoteKeyService.new.call(creator_uri) + + return if creator.nil? + + options_hash = hash(@json['signature'].without('type', 'id', 'signatureValue').merge('@context' => CONTEXT)) + document_hash = hash(@json.without('signature')) + to_be_verified = options_hash + document_hash + + if creator.keypair.public_key.verify(OpenSSL::Digest::SHA256.new, Base64.decode64(signature), to_be_verified) + creator + end + end + + def sign!(creator) + options = { + 'type' => 'RsaSignature2017', + 'creator' => [ActivityPub::TagManager.instance.uri_for(creator), '#main-key'].join, + 'created' => Time.now.utc.iso8601, + } + + options_hash = hash(options.without('type', 'id', 'signatureValue').merge('@context' => CONTEXT)) + document_hash = hash(@json.without('signature')) + to_be_signed = options_hash + document_hash + + signature = Base64.strict_encode64(creator.keypair.sign(OpenSSL::Digest::SHA256.new, to_be_signed)) + + @json.merge('@context' => merge_context(@json['@context'], CONTEXT), 'signature' => options.merge('signatureValue' => signature)) + end + + private + + def hash(obj) + Digest::SHA256.hexdigest(canonicalize(obj)) + end +end -- cgit From f095a9f8a5788aaf4205e9bdca5845a844f8c0d3 Mon Sep 17 00:00:00 2001 From: unarist Date: Sun, 27 Aug 2017 20:35:01 +0900 Subject: Allow Symbol keyed Hash in LinkedDataSignature (#4715) SerializarbleResource#as_json serializes to Symbol keyed Hash, but current implementation of LinkedDataSignature expects String keyed Hash. So it generates broken payload. --- app/lib/activitypub/linked_data_signature.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/lib/activitypub/linked_data_signature.rb') diff --git a/app/lib/activitypub/linked_data_signature.rb b/app/lib/activitypub/linked_data_signature.rb index 7173aed19..4483339a9 100644 --- a/app/lib/activitypub/linked_data_signature.rb +++ b/app/lib/activitypub/linked_data_signature.rb @@ -6,7 +6,7 @@ class ActivityPub::LinkedDataSignature CONTEXT = 'https://w3id.org/identity/v1' def initialize(json) - @json = json + @json = json.with_indifferent_access end def verify_account! -- cgit From 9a5ae096206df2240ba042efed62854193898a65 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 31 Aug 2017 21:32:09 +0200 Subject: Remove identity context from output of LinkedDataSignature (#4753) --- app/lib/activitypub/linked_data_signature.rb | 2 +- spec/lib/activitypub/linked_data_signature_spec.rb | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'app/lib/activitypub/linked_data_signature.rb') diff --git a/app/lib/activitypub/linked_data_signature.rb b/app/lib/activitypub/linked_data_signature.rb index 4483339a9..adb8b6cdf 100644 --- a/app/lib/activitypub/linked_data_signature.rb +++ b/app/lib/activitypub/linked_data_signature.rb @@ -45,7 +45,7 @@ class ActivityPub::LinkedDataSignature signature = Base64.strict_encode64(creator.keypair.sign(OpenSSL::Digest::SHA256.new, to_be_signed)) - @json.merge('@context' => merge_context(@json['@context'], CONTEXT), 'signature' => options.merge('signatureValue' => signature)) + @json.merge('signature' => options.merge('signatureValue' => signature)) end private diff --git a/spec/lib/activitypub/linked_data_signature_spec.rb b/spec/lib/activitypub/linked_data_signature_spec.rb index ee4b68028..a4d6fe8c3 100644 --- a/spec/lib/activitypub/linked_data_signature_spec.rb +++ b/spec/lib/activitypub/linked_data_signature_spec.rb @@ -63,10 +63,6 @@ RSpec.describe ActivityPub::LinkedDataSignature do expect(subject).to be_a Hash end - it 'contains signature context' do - expect(subject['@context']).to include('https://www.w3.org/ns/activitystreams', 'https://w3id.org/identity/v1') - end - it 'contains signature' do expect(subject['signature']).to be_a Hash expect(subject['signature']['signatureValue']).to be_present -- cgit