Fix processing LDSigned activities from actors with unknown public keys (#27474)
This commit is contained in:
parent
688defd60d
commit
2ffce0d5f7
2 changed files with 39 additions and 5 deletions
|
@ -18,8 +18,8 @@ class ActivityPub::LinkedDataSignature
|
||||||
|
|
||||||
return unless type == 'RsaSignature2017'
|
return unless type == 'RsaSignature2017'
|
||||||
|
|
||||||
creator = ActivityPub::TagManager.instance.uri_to_resource(creator_uri, Account)
|
creator = ActivityPub::TagManager.instance.uri_to_resource(creator_uri, Account)
|
||||||
creator ||= ActivityPub::FetchRemoteKeyService.new.call(creator_uri, id: false)
|
creator = ActivityPub::FetchRemoteKeyService.new.call(creator_uri, id: false) if creator&.public_key.blank?
|
||||||
|
|
||||||
return if creator.nil?
|
return if creator.nil?
|
||||||
|
|
||||||
|
@ -27,9 +27,9 @@ class ActivityPub::LinkedDataSignature
|
||||||
document_hash = hash(@json.without('signature'))
|
document_hash = hash(@json.without('signature'))
|
||||||
to_be_verified = options_hash + document_hash
|
to_be_verified = options_hash + document_hash
|
||||||
|
|
||||||
if creator.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), Base64.decode64(signature), to_be_verified)
|
creator if creator.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), Base64.decode64(signature), to_be_verified)
|
||||||
creator
|
rescue OpenSSL::PKey::RSAError
|
||||||
end
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def sign!(creator, sign_with: nil)
|
def sign!(creator, sign_with: nil)
|
||||||
|
|
|
@ -36,6 +36,40 @@ RSpec.describe ActivityPub::LinkedDataSignature do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when local account record is missing a public key' do
|
||||||
|
let(:raw_signature) do
|
||||||
|
{
|
||||||
|
'creator' => 'http://example.com/alice',
|
||||||
|
'created' => '2017-09-23T20:21:34Z',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:signature) { raw_signature.merge('type' => 'RsaSignature2017', 'signatureValue' => sign(sender, raw_signature, raw_json)) }
|
||||||
|
|
||||||
|
let(:service_stub) { instance_double(ActivityPub::FetchRemoteKeyService) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
# Ensure signature is computed with the old key
|
||||||
|
signature
|
||||||
|
|
||||||
|
# Unset key
|
||||||
|
old_key = sender.public_key
|
||||||
|
sender.update!(private_key: '', public_key: '')
|
||||||
|
|
||||||
|
allow(ActivityPub::FetchRemoteKeyService).to receive(:new).and_return(service_stub)
|
||||||
|
|
||||||
|
allow(service_stub).to receive(:call).with('http://example.com/alice', id: false) do
|
||||||
|
sender.update!(public_key: old_key)
|
||||||
|
sender
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fetches key and returns creator' do
|
||||||
|
expect(subject.verify_account!).to eq sender
|
||||||
|
expect(service_stub).to have_received(:call).with('http://example.com/alice', id: false).once
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'when signature is missing' do
|
context 'when signature is missing' do
|
||||||
let(:signature) { nil }
|
let(:signature) { nil }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue