summaryrefslogtreecommitdiff
path: root/server.rb
diff options
context:
space:
mode:
authorpdp8 <pdp8@pdp8.info>2023-06-26 20:49:38 +0200
committerpdp8 <pdp8@pdp8.info>2023-06-26 20:49:38 +0200
commitdfaac96870ac6a86ebb0b5e5c9365e1e0ef6e5bc (patch)
tree07f04481328a85cfe3e3ea4b8bee1a6c654636d6 /server.rb
parent8453f524515941f3c0a65b5ca3b9354be76b4c33 (diff)
digest verification, fetch/send_signed refactored
Diffstat (limited to 'server.rb')
-rw-r--r--server.rb57
1 files changed, 30 insertions, 27 deletions
diff --git a/server.rb b/server.rb
index b5076f3..75c8ede 100644
--- a/server.rb
+++ b/server.rb
@@ -79,36 +79,39 @@ helpers do
# https://github.com/mastodon/mastodon/blob/main/app/controllers/concerns/signature_verification.rb
def verify!
- # TODO verify digest
- begin
- signature_params = {}
- request.env["HTTP_SIGNATURE"].split(',').each do |pair|
- k, v = pair.split('=')
- signature_params[k] = v.gsub('"', '')
- end
-
- key_id = signature_params['keyId']
- headers = signature_params['headers']
- signature = Base64.decode64(signature_params['signature'])
- actor = fetch key_id
- key = OpenSSL::PKey::RSA.new(actor['publicKey']['publicKeyPem'])
+ # verify digest
+ request.body.rewind # in case someone already read it
+ body = request.body.read
+ sha256 = OpenSSL::Digest::SHA256.new
+ digest = "SHA-256=" + sha256.base64digest(body)
+ halt 403 unless digest == request.env["HTTP_DIGEST"]
+
+ signature_params = {}
+ request.env["HTTP_SIGNATURE"].split(',').each do |pair|
+ k, v = pair.split('=')
+ signature_params[k] = v.gsub('"', '')
+ end
- comparison = headers.split(' ').map do |signed_params_name|
- if signed_params_name == '(request-target)'
- '(request-target): post /inbox'
- elsif signed_params_name == 'content-type'
- "#{signed_params_name}: #{request.env["CONTENT_TYPE"]}"
- else
- "#{signed_params_name}: #{request.env["HTTP_" + signed_params_name.upcase]}"
- end
- end.join("\n")
+ key_id = signature_params['keyId']
+ headers = signature_params['headers']
+ signature = Base64.decode64(signature_params['signature'])
+
+ actor = fetch key_id
+ halt 403 unless actor
+ key = OpenSSL::PKey::RSA.new(actor['publicKey']['publicKeyPem'])
+
+ comparison = headers.split(' ').map do |signed_params_name|
+ if signed_params_name == '(request-target)'
+ '(request-target): post /inbox'
+ elsif signed_params_name == 'content-type'
+ "#{signed_params_name}: #{request.env["CONTENT_TYPE"]}"
+ else
+ "#{signed_params_name}: #{request.env["HTTP_" + signed_params_name.upcase]}"
+ end
+ end.join("\n")
- halt 400 unless key.verify(OpenSSL::Digest.new('SHA256'), signature, comparison)
- rescue => e
- p request.env["HTTP_SIGNATURE"], e
- halt 400
- end
+ halt 403 unless key.verify(OpenSSL::Digest.new('SHA256'), signature, comparison)
end
def create object