Mesut Başaran
Mesut Başaran

Reputation: 977

Rsa Signature Header Verification

I am testing the signature verification in: https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-07#appendix-C

I took the public key from the sample and verify the signature with headers This is my code in C#

     public async Task<string> VerifyTest()
    {


        SigningString += "(request-target): post/foo?param=value&pet=dog" + "\n";
        SigningString += "host: example.com\n";
        SigningString += "date: Thu, 05 Jan 2014 21:31:40 GMT\n";
        SigningString += "content-type: application/json\n";
        SigningString += "digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=\n";
        SigningString += "content-length: 18";

        string Signature = @"jgSqYK0yKclIHfF9zdApVEbDp5eqj8C4i4X76pE+XHoxugXv7qnVrGR+30bmBgtpR39I4utq17s9ghz/2QFVxlnToYAvbSVZJ9ulLd1HQBugO0jOyn9sXOtcN7uNHBjqNCqUsnt0sw/cJA6B6nJZpyNqNyAXKdxZZItOuhIs78w=";


        string ClientPublicKey = @"-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCFENGw33yGihy92pDjZQhl0C36rPJj+CvfSC8+q28hxA161QFNUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6Z4UMR7EOcpfdUE9Hf3m/hs+FUR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJwoYi+1hqp1fIekaxsyQIDAQAB-----END PUBLIC KEY-----";



        string x509Pem = ClientPublicKey;

        byte[] message = Encoding.UTF8.GetBytes(SigningString);
        byte[] signature = Convert.FromBase64String(Signature);

        byte[] Sha256Message = SHA256.Create().ComputeHash(message);
        string x = Convert.ToBase64String(Sha256Message);


        PemReader pr = new PemReader(new StringReader(x509Pem));
        AsymmetricKeyParameter publicKey = (AsymmetricKeyParameter)pr.ReadObject();

        RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)publicKey);
        RSACng rsaCng = new RSACng();
        rsaCng.ImportParameters(rsaParams);

        var boolHash = rsaCng.VerifyHash(Sha256Message, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);



        return boolHash.ToString();
    }

Where am i doing wrong ?

Edit:

I want to verify the http request's header.The request has authorization header which has signature of the request.The request headers are taken from :

https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-07#appendix-C.3

This is the request headers :

   (request-target): post /foo?param=value&pet=dog
   host: example.com
   date: Thu, 05 Jan 2014 21:31:40 GMT
   content-type: application/json
   digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
   content-length: 18

This is the authorization header in request:

Authorization: Signature keyId="Test",algorithm="rsa-sha256",
headers="(request-target) host date content-type digest content-length",
signature="jgSqYK0yKclIHfF9zdApVEbDp5eqj8C4i4X76pE+XHoxugXv7q
nVrGR+30bmBgtpR39I4utq17s9ghz/2QFVxlnToYAvbSVZJ9ulLd1HQBugO0j
Oyn9sXOtcN7uNHBjqNCqUsnt0sw/cJA6B6nJZpyNqNyAXKdxZZItOuhIs78w="

The signature field in authorization header is the encrypted base64 string of request headers with rsa private key.

I want to verify the request header with client public key. The keys are located in there : https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-07#appendix-C

But the signatures mismatch.Any help will be great. Thank you.

Upvotes: 1

Views: 1391

Answers (1)

Topaco
Topaco

Reputation: 49470

The reference used is a draft from July 2017 (draft-cavage-http-signatures-07). The test data just seems to be wrong!

There is a more recent draft from October 2019 (draft-cavage-http-signatures-12). The values used there can be verified successfully.

Both drafts use the same keys. The differences are in the date part and in the signature.

The code below demonstrates the successful verification with the data from draft-cavage-http-signatures-12 and the failed verification with the data from draft-cavage-http-signatures-07:

string x509Pem = @"-----BEGIN PUBLIC KEY-----
                   MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCFENGw33yGihy92pDjZQhl0C3
                   6rPJj+CvfSC8+q28hxA161QFNUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6
                   Z4UMR7EOcpfdUE9Hf3m/hs+FUR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJw
                   oYi+1hqp1fIekaxsyQIDAQAB
                   -----END PUBLIC KEY-----";

// Verification draft 12: succeeds
string messageStr = "(request-target): post /foo?param=value&pet=dog\n"
                      + "host: example.com\n"
                      + "date: Sun, 05 Jan 2014 21:31:40 GMT\n"
                      + "content-type: application/json\n"
                      + "digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=\n"
                      + "content-length: 18";
string signatureB64 = "vSdrb+dS3EceC9bcwHSo4MlyKS59iFIrhgYkz8+oVLEEzmYZZvRs8rgOp+63LEM3v+MFHB32NfpB2bEKBIvB1q52LaEUHFv120V01IL+TAD48XaERZFukWgHoBTLMhYS2Gb51gWxpeIq8knRmPnYePbF5MOkR0Zkly4zKH7s1dE=";
Console.WriteLine(VerifyTest(messageStr, signatureB64, x509Pem)); // True

// Verification draft 7: fails
messageStr = "(request-target): post /foo?param=value&pet=dog\n"
              + "host: example.com\n"
              + "date: Thu, 05 Jan 2014 21:31:40 GMT\n"
              + "content-type: application/json\n"
              + "digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=\n"
              + "content-length: 18";
signatureB64 = "jgSqYK0yKclIHfF9zdApVEbDp5eqj8C4i4X76pE+XHoxugXv7qnVrGR+30bmBgtpR39I4utq17s9ghz/2QFVxlnToYAvbSVZJ9ulLd1HQBugO0jOyn9sXOtcN7uNHBjqNCqUsnt0sw/cJA6B6nJZpyNqNyAXKdxZZItOuhIs78w=";
Console.WriteLine(VerifyTest(messageStr, signatureB64, x509Pem)); // False

with your slightly modified VerifyTest():

public static bool VerifyTest(string messageStr, string signatureB64, string x509Pem)
{
    byte[] message = Encoding.UTF8.GetBytes(messageStr);
    byte[] signature = Convert.FromBase64String(signatureB64);
    byte[] sha256Message = SHA256.Create().ComputeHash(message);

    PemReader pr = new PemReader(new StringReader(x509Pem));
    AsymmetricKeyParameter publicKey = (AsymmetricKeyParameter)pr.ReadObject();

    RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)publicKey);
    RSACng rsaCng = new RSACng();
    rsaCng.ImportParameters(rsaParams);
    var verified = rsaCng.VerifyHash(sha256Message, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

    return verified;
}

Upvotes: 1

Related Questions