Подписание и проверка RSA с помощью C#, BouncyCastle и импортированного ключа RSA — рабочий пример Python и нерабочий образец кода C# внутри

Я рвал на себе то, что осталось от моих волос, пытаясь получить тривиальный пример подписи и проверки данных RSA с работающими C# и BouncyCastle.

RSACryptoServiceProvider.VerifyHash() всегда возвращает false в примере, который у меня работает с Python и M2Crypto.

Я убедился, что хэш-подписи идентичны между рабочим примером и примером C#, и именно здесь я застрял. Я чувствую, что упускаю какую-то важную деталь.

Далее следуют рабочий код Python и нерабочий код C#.

Ключ был сгенерирован с помощью

openssl genrsa -out testkey.pem 1024
openssl rsa -in testkey.pem -pubout > testkey.pub

Код Python (работает):

    private = """-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCxSHbp1ID/XHEdzVzgqYR1F/79PeMbqzuKNZChvt1gFObBhKyB
pgaHDHw3UZrO8s/hBEE/Mpe2Lh90ZAFdPIXq+HyVoznXMoJYBv0uLDApvSQbJNOd
f7T5VwmpBbkfj1NAlm39Eun9uBSokEOnB24g+bczPQPGOASrQ2Ly9afOZQIDAQAB
AoGBAIEzQIZ1OnXgVwfTLMcGg+QaUtkYizUU+9Vj6D4YrZliYjHSkS4DY2p0rOpb
7Ki5yMpCoZJ/OpWo03+tilj6zNUU6X3aHrPPSv8jcsE0sDi9zYJr/Ztk3EG23sad
bM28Bb4fV/Z0/E6FZJrmuvI2dZP/57oQSHGOhtkHFO21cW5BAkEA3l/i5Rc34YXc
WHYEsOYe0kAxS4dCmhbLWaWvsghW/TomjdxzePsO70GZZqRMdzkfA1iS1OrK+pP4
4suL2rSLrQJBAMwXFnBp4Jmek0CTSxoYf6q91eFm/IRkGLnzE1fEZ76vQOBTas8T
/mpjNQHSEywo/QB62h9A8hy7XNrfZJAMJJkCQA5TYwybKFBxDTbts3Op/4ZP+F0D
Q7klisglsmHnw6Lgoic1coLyuY2UTkucfgiYN3VBuYPZ9GWcLsZ9km7ufqkCQQCz
NVa70Qyqd+cfXfcla/u2pskHCtKTQf3AUmRavhjHBMa39CemvAy7yG9EMP4q2bcH
U9jydqnidtdbTavVHQSJAkA0zJtLzHGPtQqQaI7K6kBDXYPqloGnQxHxad0HPx2e
Vj2qv1tEsqeG6HC7aL/afXOtxcfjq4oMHbGUjDv+dGfP
-----END RSA PRIVATE KEY-----"""

public = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxSHbp1ID/XHEdzVzgqYR1F/79
PeMbqzuKNZChvt1gFObBhKyBpgaHDHw3UZrO8s/hBEE/Mpe2Lh90ZAFdPIXq+HyV
oznXMoJYBv0uLDApvSQbJNOdf7T5VwmpBbkfj1NAlm39Eun9uBSokEOnB24g+bcz
PQPGOASrQ2Ly9afOZQIDAQAB
-----END PUBLIC KEY-----"""

message = "test input string"

import base64

# Use EVP api to sign message
from M2Crypto import EVP
key = EVP.load_key_string(private)
key.reset_context(md='sha1')
key.sign_init()
key.sign_update(message)
signature = key.sign_final()

encoded = base64.b64encode(signature)
print encoded

with open("python_sig2.txt","w") as f:
    f.write(encoded)

# Use EVP api to verify signature
from M2Crypto import BIO, RSA, EVP
bio = BIO.MemoryBuffer(public)
rsa = RSA.load_pub_key_bio(bio)
pubkey = EVP.PKey()
pubkey.assign_rsa(rsa)
pubkey.reset_context(md="sha1")
pubkey.verify_init()
pubkey.verify_update(message)
decoded = base64.b64decode(encoded)
print pubkey.verify_final(decoded) == 1

Код C# (verifyhash() возвращает false):

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;


namespace RsaSignTest
{
    class Program
    {
        private const string privateKey =
            @"-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCxSHbp1ID/XHEdzVzgqYR1F/79PeMbqzuKNZChvt1gFObBhKyB
pgaHDHw3UZrO8s/hBEE/Mpe2Lh90ZAFdPIXq+HyVoznXMoJYBv0uLDApvSQbJNOd
f7T5VwmpBbkfj1NAlm39Eun9uBSokEOnB24g+bczPQPGOASrQ2Ly9afOZQIDAQAB
AoGBAIEzQIZ1OnXgVwfTLMcGg+QaUtkYizUU+9Vj6D4YrZliYjHSkS4DY2p0rOpb
7Ki5yMpCoZJ/OpWo03+tilj6zNUU6X3aHrPPSv8jcsE0sDi9zYJr/Ztk3EG23sad
bM28Bb4fV/Z0/E6FZJrmuvI2dZP/57oQSHGOhtkHFO21cW5BAkEA3l/i5Rc34YXc
WHYEsOYe0kAxS4dCmhbLWaWvsghW/TomjdxzePsO70GZZqRMdzkfA1iS1OrK+pP4
4suL2rSLrQJBAMwXFnBp4Jmek0CTSxoYf6q91eFm/IRkGLnzE1fEZ76vQOBTas8T
/mpjNQHSEywo/QB62h9A8hy7XNrfZJAMJJkCQA5TYwybKFBxDTbts3Op/4ZP+F0D
Q7klisglsmHnw6Lgoic1coLyuY2UTkucfgiYN3VBuYPZ9GWcLsZ9km7ufqkCQQCz
NVa70Qyqd+cfXfcla/u2pskHCtKTQf3AUmRavhjHBMa39CemvAy7yG9EMP4q2bcH
U9jydqnidtdbTavVHQSJAkA0zJtLzHGPtQqQaI7K6kBDXYPqloGnQxHxad0HPx2e
Vj2qv1tEsqeG6HC7aL/afXOtxcfjq4oMHbGUjDv+dGfP
-----END RSA PRIVATE KEY-----";

        private const string publicKey =
            @"-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxSHbp1ID/XHEdzVzgqYR1F/79
PeMbqzuKNZChvt1gFObBhKyBpgaHDHw3UZrO8s/hBEE/Mpe2Lh90ZAFdPIXq+HyV
oznXMoJYBv0uLDApvSQbJNOdf7T5VwmpBbkfj1NAlm39Eun9uBSokEOnB24g+bcz
PQPGOASrQ2Ly9afOZQIDAQAB
-----END PUBLIC KEY-----";

        static void Main(string[] args)
        {
            var data = "test input string";
            var sig = SignWithPrivateKey(data);
            var valid = VerifyWithPublicKey(data,sig);
        }

        private static byte[] SignWithPrivateKey(string data)
        {
            RSACryptoServiceProvider rsa;

            using (var keyreader = new StringReader(privateKey))
            {
                var pemreader = new PemReader(keyreader);
                var y = (AsymmetricCipherKeyPair) pemreader.ReadObject();
                var rsaPrivKey = (RsaPrivateCrtKeyParameters)y.Private;
                rsa = (RSACryptoServiceProvider)RSACryptoServiceProvider.Create();
                var rsaParameters = DotNetUtilities.ToRSAParameters(rsaPrivKey);
                rsa.ImportParameters(rsaParameters);

            }

            // compute sha1 hash of the data
            var sha = new SHA1CryptoServiceProvider();
            byte[] hash = sha.ComputeHash(Encoding.ASCII.GetBytes(data));

            // actually compute the signature of the SHA1 hash of the data
            var sig = rsa.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));

            // base64 encode the signature and write to compare to the python version
            String b64signature = Convert.ToBase64String(sig);
            using (var sigwriter = new StreamWriter(@"C:\scratch\csharp_sig2.txt"))
            {
                sigwriter.Write(b64signature);
            }

            return sig;
        }

        private static bool VerifyWithPublicKey(string data,byte[] sig)
        {
            RSACryptoServiceProvider rsa;

            using (var keyreader = new StringReader(publicKey))
            {
                var pemReader = new PemReader(keyreader);
                var y = (RsaKeyParameters) pemReader.ReadObject();
                rsa = (RSACryptoServiceProvider) RSACryptoServiceProvider.Create();
                var rsaParameters = new RSAParameters();
                rsaParameters.Modulus = y.Modulus.ToByteArray();
                rsaParameters.Exponent = y.Exponent.ToByteArray();
                rsa.ImportParameters(rsaParameters);
            }

            // compute sha1 hash of the data
            var sha = new SHA1CryptoServiceProvider();
            byte[] hash = sha.ComputeHash(Encoding.ASCII.GetBytes(data));

            // This always returns false
            return rsa.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"),sig);
        }
    }
}

На данный момент я не знаю, что делать, и любая помощь будет очень полезна. оценил.

9
задан amckinley 22 March 2012 в 12:51
поделиться