Not able to verify Signature of Mastodon activity

Hey! I’m currently working on a new AP project/tool i will reveal in upcoming weeks or months but i got stuck on the Signature verification part. I’m using Ruby to implement that all but the code is probably easy enough to understand no matter what’s your primary coding language of choice.

Here is a sample request I’m receiving:

# Body
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://mastodon.social/d24c6ff9-230e-4502-823e-19e2d9059c79",
  "type": "Follow",
  "actor": "https://mastodon.social/users/mbajur",
  "object": "https://aptest.mbajur.com/ap/objects/f3b8ff84-d044-47dd-bfeb-bb01c338f02a"
}

# Headers
{
  "HTTP_HOST": "aptest.mbajur.com",
  "HTTP_USER_AGENT": "http.rb/5.2.0 (Mastodon/4.3.0-nightly.2024-05-17; +https://mastodon.social/)",
  "HTTP_ACCEPT_ENCODING": "gzip",
  "CONTENT_TYPE": "application/activity+json",
  "HTTP_DATE": "Wed, 29 May 2024 08:13:30 GMT",
  "HTTP_DIGEST": "SHA-256=r+DkjuOvEXGwY+2+Fe84XwLDBWMvYdRzsMvzRayg3K8=",
  "HTTP_SIGNATURE": "keyId=\"https://mastodon.social/users/mbajur#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest content-type\",signature=\"teneZcdVEron+Am1GEayOc8vf4qx1J7AF8kHZ4dTCtonmsJumUHh1Q/688nc2W9oSYf6yywJHpRvmi5TBIN3r1QBQmAG+bvolI1MISQw2l3j5HVm+zu6oPSCZ1KuUwEFV5kIgb0zBclEMsAk0lAPl3kBPc0whQJuIW4yq90Xj5AiSZMKrDyDOsJ3bYVAN760wZetMEM7Vzt0CucG/fBNzOe4a9XfoO42t1XhiNfAllXtm0Obj9W8XtkXOrxqlKYpc2W2ZvwBDQwgaFBu4ciF2l8RYwezoPLR8NkujrYfhrOVxNDvnEiVISdpAJqDhktEvQ3+Gy8BSyIP7mlRHNCxnA==\""
}

And now, I’m trying to verify the Signature header sent using http-signature gem. This lib has not been updated in like 6 years so that might be a bit risky to base my judgement and code on that but it has a working specs coverage and let’s me generate signatures i can verify as working later so i guess we can assume that it’s working as expected. Anyway, here is my verifying code:

headers = {
  host: "aptest.mbajur.com",
  content_type: 'application/activity+json',
  date: "Wed, 29 May 2024 08:13:30 GMT",
  digest: "SHA-256=r+DkjuOvEXGwY+2+Fe84XwLDBWMvYdRzsMvzRayg3K8=",
  signature: "keyId=\"https://mastodon.social/users/mbajur#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest content-type\",signature=\"teneZcdVEron+Am1GEayOc8vf4qx1J7AF8kHZ4dTCtonmsJumUHh1Q/688nc2W9oSYf6yywJHpRvmi5TBIN3r1QBQmAG+bvolI1MISQw2l3j5HVm+zu6oPSCZ1KuUwEFV5kIgb0zBclEMsAk0lAPl3kBPc0whQJuIW4yq90Xj5AiSZMKrDyDOsJ3bYVAN760wZetMEM7Vzt0CucG/fBNzOe4a9XfoO42t1XhiNfAllXtm0Obj9W8XtkXOrxqlKYpc2W2ZvwBDQwgaFBu4ciF2l8RYwezoPLR8NkujrYfhrOVxNDvnEiVISdpAJqDhktEvQ3+Gy8BSyIP7mlRHNCxnA==\""
}

body = {
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://mastodon.social/d24c6ff9-230e-4502-823e-19e2d9059c79",
  "type": "Follow",
  "actor": "https://mastodon.social/users/mbajur",
  "object": "https://aptest.mbajur.com/ap/objects/f3b8ff84-d044-47dd-bfeb-bb01c338f02a"
}

public_key = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0sirgrt7253i6vevwoJ6\nfd1TCeqTdMQ98BhhtD6KvEmQFZa+tjCj9bCOIb0CkysAddnSpNwE4Xx517opgYiO\nZx95QXtRCAZ/Th/ZUMrEku9pmSZMo9/DyjFmivzgeBu5PTGnczFqg7J5dihDJgBV\njaB2bUymSI9ou44o62ZNBMA7xT3OytOac37NobelhyCLz1V/CdKMtPDFrM64fMy5\nbWJwZIhAZUeVvSpy88/OCBid1nM7wZ2gjK9rVNXX+ogbFYU59rfymYJuMGvCqaHi\nVl59KKA34es7oNyLBxVGBjZU1qaKbN6KRVC6tiwc9cJspA/s953guohf+ZIUtDas\nvwIDAQAB\n-----END PUBLIC KEY-----\n"

HTTPSignature.valid?(
  url: 'https://aptest.mbajur.com/ap/objects/f3b8ff84-d044-47dd-bfeb-bb01c338f02a/inbox',
  method: :post,
  headers: headers,
  body: body.to_json,
  key: OpenSSL::PKey::RSA.new(public_key),
  algorithm: 'rsa-sha256'
)
# => false

And yet, this signature is being verified as invalid. Is there anything in here you can see being obviously wrong? The process of signature verification is completely non-verbose and i have no idea what can i do to troubleshoot that. Thanks in advance!

Alright, it seems it was actually a lib issue as i was able to use another library to verify the signature. Here is the working code sample if anyone needs it:

require 'http_signatures'

headers = {
  host: "aptest.mbajur.com",
  content_type: 'application/activity+json',
  date: "Wed, 29 May 2024 07:29:55 GMT",
  digest: "SHA-256=WjyyKQFwAdhnT/WFo4fgwNPNqOF/zq6jxq8LkN0EVnQ=",
  signature: "keyId=\"https://mastodon.social/users/mbajur#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest content-type\",signature=\"o8EzUJcKoucHLvZOF9pw0eks7otWeM2So3vpDu6xxCVJ9I3/JQvjlqvhjsH6885unWp+U00EKpB7q86Gm6JDjjoE7dHil0NCuwOMFoxV29QEZERsJW4UE8s2BSgbRxT6JjpV6tfWSFFkKp/uMqlxpoNrsMR908F3kbh58AuygLnIFlEHXMld9TGRjq8zB3PySqZYqatGg1jvCQja1Y8W/x6GM09yI7TzYRw6UeJUw/ZjZvo1+uFMM3EITGzcmrtuyT9Hre+NVwJM/xehH92k0AV/PB8sSZlLYJED1kDwocmpbUWCJ9oBYEPBBnxl5KttKYUzv7KDX3q3CQV5/r3+SA==\""
}

body = {
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://mastodon.social/93c2ff7d-b1e3-4a06-890d-861786f47b54",
  "type": "Follow",
  "actor": "https://mastodon.social/users/mbajur",
  "object": "https://aptest.mbajur.com/ap/objects/f3b8ff84-d044-47dd-bfeb-bb01c338f02a"
}

pub_key = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0sirgrt7253i6vevwoJ6\nfd1TCeqTdMQ98BhhtD6KvEmQFZa+tjCj9bCOIb0CkysAddnSpNwE4Xx517opgYiO\nZx95QXtRCAZ/Th/ZUMrEku9pmSZMo9/DyjFmivzgeBu5PTGnczFqg7J5dihDJgBV\njaB2bUymSI9ou44o62ZNBMA7xT3OytOac37NobelhyCLz1V/CdKMtPDFrM64fMy5\nbWJwZIhAZUeVvSpy88/OCBid1nM7wZ2gjK9rVNXX+ogbFYU59rfymYJuMGvCqaHi\nVl59KKA34es7oNyLBxVGBjZU1qaKbN6KRVC6tiwc9cJspA/s953guohf+ZIUtDas\nvwIDAQAB\n-----END PUBLIC KEY-----\n"

$context = HttpSignatures::Context.new(
  keys: {"https://mastodon.social/users/mbajur#main-key" => { public_key: pub_key }},
  algorithm: "rsa-sha256",
  headers: headers,
)

message = Net::HTTP::Post.new(
  "/ap/objects/f3b8ff84-d044-47dd-bfeb-bb01c338f02a/inbox",
  "Date" => headers[:date],
  'Content-Type' => headers[:content_type],
  'Digest' => headers[:digest],
  'Signature' => headers[:signature],
  'Host' => headers[:host]
)
message.body = body

$context.verifier.valid?(message)
# => true
1 Like