Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add digest to deliver.rb #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ To deliver our message, we will use POST it to the inbox of the person we are re

HTTP signatures is one of those things that are much easier to do with actual code instead of manually. The signature looks like this:

Signature: keyId="https://my-example.com/actor#main-key",headers="(request-target) host date",signature="..."
Signature: keyId="https://my-example.com/actor#main-key",headers="(request-target) host date digest",signature="..."

The `keyId` refers to public key of our actor, the `header` lists the headers that are used for building the signature, and then finally, the `signature` string itself. The order of the headers must be the same in plain-text and within the to-be-signed string, and header names are always lowercase. The `(request-target)` is a special, fake header that pins down the HTTP method and the path of the destination.

Expand All @@ -124,6 +124,7 @@ The to-be-signed string would look something like this:
(request-target): post /inbox
host: mastodon.social
date: Sun, 06 Nov 1994 08:49:37 GMT
digest: {sha-256 hash of create-hello-world.json}

Mind that there is only a ±30 seconds time window when that signature would be considered valid, which is a big reason why it’s quite difficult to do manually. Anyway, assuming we’ve got the valid date in there, we now need to build a signed string out of it. Let’s put it all together:

Expand All @@ -132,13 +133,15 @@ require 'http'
require 'openssl'

document = File.read('create-hello-world.json')
sha256 = OpenSSL::Digest::SHA256.new
digest = "SHA-256=" + Base64.strict_encode64(sha256.digest(document))
date = Time.now.utc.httpdate
keypair = OpenSSL::PKey::RSA.new(File.read('private.pem'))
signed_string = "(request-target): post /inbox\nhost: mastodon.social\ndate: #{date}"
signed_string = "(request-target): post /inbox\nhost: mastodon.social\ndate: #{date}\ndigest: #{digest}"
signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest::SHA256.new, signed_string))
header = 'keyId="https://my-example.com/actor",headers="(request-target) host date",signature="' + signature + '"'
header = 'keyId="https://my-example.com/actor",headers="(request-target) host date digest",signature="' + signature + '"'

HTTP.headers({ 'Host': 'mastodon.social', 'Date': date, 'Signature': header })
HTTP.headers({ 'Host': 'mastodon.social', 'Date': date, 'Signature': header, 'Digest': digest })
.post('https://mastodon.social/inbox', body: document)
```

Expand Down