Ranx
Ranx

Reputation: 49

Sign with PHP, verify with C#

A have PHP code to sign the message (using phpseclib 2.0):

function sign($plaintext, $key, $password) {
    $rsa = new RSA();

    $rsa->setPassword($password);
    $rsa->loadKey(file_get_contents($key));

    $rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
    $signature = $rsa->sign(hash('sha256', $plaintext));

    return base64_encode($signature);
}

Public and private keys format is PEM. I need to verify this signature with C#. I am trying this code, but it returns false:

public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey)
{
    bool success = false;
    using (var rsa = new RSACryptoServiceProvider())
    {
    var encoder = new UTF8Encoding();
    byte[] bytesToVerify = encoder.GetBytes(originalMessage);
    byte[] signedBytes = Convert.FromBase64String(signedMessage);
    try
    {
        rsa.ImportParameters(publicKey);

        SHA256Managed Hash = new SHA256Managed();

        byte[] hashedData = Hash.ComputeHash(bytesToVerify);
        success = rsa.VerifyData(hashedData, CryptoConfig.MapNameToOID("SHA256"), signedBytes);
    }
    catch (CryptographicException e)
    {
        Console.WriteLine(e.Message);
    }
    finally
    {
        rsa.PersistKeyInCsp = false;
    }
    }
    return success;
}

Usage:

RSACryptoServiceProvider rsa = PemKeyUtils.PemKeyUtils.GetRSAProviderFromPemFile("public.key");
MessageBox.Show(VerifyData("my message", @"ZpQMPYlMIgME/H0sRYBnyEf/yJ/eBc5bznYZ2nMFn/I6Ts3u8P3x0QgzbUxPnhUgfKhcrEC2UgffyzWzCfwT3Bs+lm6Q89N5bkWK08WKnWaFxr2GQ6+gNyPyUKUgfy851xIHU7EMR6bZt/IndPC+lAAXSxxddPwLelrI8ktgyMVvMUzfCh3AeNCBuY5sSRwkAKH2myPBThJKNjKSZVEb4tO4oiPPWlBuifqmWvbQeMFuKANY0dZNCUFVjlnkaHnwVNzVs1BhNTEML2MKmWvKofafbtcG8J1F+7PapppZwT7OFqhosCSrrzRX49cR4y/7b0syJozmJSebKDpy6FPefA==", rsa.ExportParameters(false)).ToString());

PemKeyUtils class from this answer.

What's wrong? How can I verify signature with C#?

Upvotes: 0

Views: 432

Answers (1)

President James K. Polk
President James K. Polk

Reputation: 41958

VerifyData() computes the hash itself, so you've ended up hashing the data twice in your C# code. Just provide the data directly to VerifyData() without hashing it yourself.

EDIT: Ok, now I see that you are also hashing it twice on the php side, the first time with SHA1 and the second time with SHA256. Just hash it once, using SHA256, just it like shows in the examples.

function sign($plaintext, $key, $password) {
    $rsa = new RSA();

    $rsa->setPassword($password);
    $rsa->loadKey(file_get_contents($key));

    $rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
    $rsa->setHash('sha256')
    $signature = $rsa->sign($plaintext);

    return base64_encode($signature);
}

Upvotes: 1

Related Questions