[ActivityPub] Signed request date outside acceptable time window for correct params

I am trying to support activitypub for my application. I was able to follow users from my application but unable to see activity as toots on mastodon timeline. I realised that I need to post the activity to my mastodon user inbox. However all my inbox requests fail with: “Signed request date outside acceptable time window”

My code:

require 'http'
require 'openssl'

def verify_sign(key, signature, data)
  # Verifies with a public key that the data was signed with their private key 
  pubkey = key.public_key 
  if pubkey.verify(OpenSSL::Digest::SHA256.new, signature, data)
    puts 'the signature is valid'
  else
    puts 'the signature is invalid'
  end
end

document = {
  "id": "http://053783c3c94f.ngrok.io/activity/5",
  "type": "Create",
  "actor": "http://053783c3c94f.ngrok.io/people/1_Gaurav_Koley",
  "published": "2020-05-30T18:00:35.699Z",
  "to": ["https://www.w3.org/ns/activitystreams#Public"],
  "cc": ["https://mastodon.social/users/arkokoley/followers"],
  "object": {
    "id": "http://053783c3c94f.ngrok.io/activity/5",
    "type": "Note",
    "published": "2020-05-30T12:10:45Z",
    "content": "hello",
    "url": "http://053783c3c94f.ngrok.io/resources/1",
    "attributedTo": "http://053783c3c94f.ngrok.io/people/1_Gaurav_Koley",
    "to": ["https://www.w3.org/ns/activitystreams#Public"]
  }
}
date = Time.now.utc.httpdate
keypair = OpenSSL::PKey::RSA.new(File.read('private.pem'), 'gratia')
signed_string = "(request-target): post /inbox\nhost: mastodon.social\ndate: #{date}\n"
sign = keypair.sign(OpenSSL::Digest::SHA256.new, signed_string)
signature = Base64.strict_encode64(sign)
header = 'keyId="https://053783c3c94f.ngrok.io/people/1_Gaurav_Koley",headers="'+ signed_string +'",signature="' + signature + '"'

response = HTTP.headers({ 'Host': 'mastodon.social', 'Date': date, 'Signature': header })
    .post('https://mastodon.social/inbox', body: document.to_json)

puts response.to_json

key = OpenSSL::PKey::RSA.new(keypair.public_key.to_pem.to_s)
s = Base64.decode64(signature)
verify_sign(keypair, s, signed_string)

Not sure what is wrong.

What happens if you don’t supply and sign Date header?

It looks to me that you should not give signed_string as a value to the headers= attribute.

Hi @saper, not supplying and signing the Date header is giving me following response:

“Incompatible request signature”

Sending the headers as:

header = 'keyId="https://053783c3c94f.ngrok.io/people/1_Gaurav_Koley",headers="(request-target) host date",signature="' + signature + '"'

as mentioned in https://blog.joinmastodon.org/2018/06/how-to-implement-a-basic-activitypub-server/ gives me the following response:
“Verification failed for 1_Gaurav_Koley@053783c3c94f.ngrok.io Gaurav Koley | Gratia

But if you are not sending the “Date” header it should be removed from the headers part of the header?

Since you are writing Ruby, you can have a look at the Mastodon’s signature verification code:

I have removed the date from the header as well as the signature. After doing that, I get the “Incompatible request signature” response.

I have taken a look at Mastodon’s signature verification code. The error seems to come from the ‘matches_time_window?’ function. But it shouldn’t fail because when i run the same code as the ‘matches_time_window’ function, i get true.

Any reference code that I can look up? @gargron

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.