High
High

Reputation: 626

C# Verify Json string via signature and RSA public key

I'm creating an IAP plugin for the local Android market that I think has similar API as google play.

I build an Android side and it will return all response from the market to the unity c# side.
All part working fine but I can't figure out how to verify the signature of the response.

I'm new in cryptography and searching day to day about this.

Please correct me if I'm wrong.

  1. They use a hash algorithm to sign data and encrypt that hash with private key.
    I must decrypt signature with public key and compare hashes.

This is my public key (Base64):

MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBrwDltnT/AaF3oMt+F3lza5JEvce0GLS1L9v9Z53lQ3LNluGk0eI2ukgWm7tAiIOLQgn11Sb9mW2VWkYTWGnZ1AZtY0GwdUQJUr7u3CWNznE6XH4UCVOVhGDCLnFrG8BcfDelhcfReGZQ3izOefhc4Oq6vZf5PfLwximK+FH27fR6XL8vg3yyK4LSwT764Dfd6H3IGes6EdTx/C3C690jdyMvhi2Q3qBiqfepHzW/jV8CAwEAAQ==

This key is in ASN.1 DER format.

I break it out and find this data:

SEQUENCE
  SEQUENCE
    OBJECT IDENTIFIER 1.2.840.113549.1.1.1 rsaEncryption(PKCS #1)
    NULL
  BIT STRING
    SEQUENCE
      INTEGER 969837669069837851043825067021609343597253227631794160042862620526559…
      INTEGER 65537
  1. As I read on net first INTEGER is Modules and second INTEGER is Exponent

So in c# write a code like this =>

var parameter = new RSAParameters
{
    Modulus = HexToByteArray(/* "first_INTEGET" */),
    Exponent = BitConverter.GetBytes(/* "second_INTEGER" */)
};

Market send me a Json like this:

{"orderId": "0j8oJgE0Bett-neB", "purchaseToken": "0j8oJgE0Bett-neB", "developerPayload": "payload", "packageName": "com.some.market", "purchaseState": 0, "purchaseTime": 1520676644872, "productId": "card-1"}

The signature is like this:

hTFeQd25PZJ2DhGmXd0eO+C+oBeWsg983I4e5ztXtKAUrOIaNBaqAxHU3vW8acBs1I9fE5cxx/DI/sQGY4QSvpDnSm9aYz3do3joHPOXIVvXjSJfejxwzp9DKMUPd6LrgtxkaGevG+94NuKHFxpCdZlovEPXRJZyEznbASuYLqeW0KjP3jnvvw2O5iNlQRdh98h4Q18bSsaxq9zaRKExFLHkhNf/yO5m84kRB1G8

I'm searched for a method to do this but I don't know which method is true for me. My verify code is this:

using (var rsa = new RSACryptoServiceProvider())
{
    rsa.ImportParameters(parameter);
    var hash = new SHA1Managed();
    bool dataOK = 
    rsa.VerifyData(hash.ComputeHash(Encoding.UTF8.GetBytes(json)), CryptoConfig.MapNameToOID("SHA1"), Encoding.UTF8.GetBytes(signature));
}
  1. How truly convert signature to byte[] to verify? (with encoding or what???)

I'm searching a lot but more search more confuse.

Am I going the wrong way or using wrong method or ...?

  1. Why should workflow be complicated?

Can anyone help me, please?

Thanks.

Upvotes: 2

Views: 1447

Answers (1)

Maarten Bodewes
Maarten Bodewes

Reputation: 93948

OK, I'll answer in order:

  1. They use a hash algorithm to sign data and encrypt that hash with private key. I must decrypt signature with public key and compare hashes.

    No, that's not correct. You should use a signature verification method, as you're currently doing. Seeing signature as encryption of a hash is incorrect; even the latest RSA standards go out of their way to explain this. For RSA the internal padding method is different. For ECDSA there is no direct encryption/decryption possible using the same scheme.

  2. As I read on net first INTEGER is Modules and second INTEGER is Exponent

    Yes, although it is spelled modulus, not modules. It is the public exponent, there is also a private exponent for the private key. Also without the caps.

  3. How truly convert signature to byte[] to verify? (with encoding or what???)

    Standard Base 64 is already mentioned in the comment section. Note that the key and signature size are not common (but that's OK in itself).

  4. Why should workflow be complicated?

    Well, somebody has to code it in the end and crypto is hard. But to make it easier for you: the entire ASN.1 structure is called a SubjectPublicKeyInfo structure; if you look on the internet you will find pre-made code to import from such a structure.

To finally verify the structure: make sure that you use the correct signature format (RSA-PKCS#1 v1.5 or RSA-PSS) and that you know exactly which binary data is fed to the signature generation function. For instance, the signature over the JSON could be in ASCII or UTF-8 or it could be in UTF-16 LE or BE.

Better ask the creator of the signature.

Upvotes: 2

Related Questions