2012-03-22 59 views
7

Tôi đã rách phần tóc còn lại của tôi đang cố gắng lấy một ví dụ tầm thường về ký kết và xác minh dữ liệu RSA với C# và BouncyCastle hoạt động.Ký và xác minh RSA với C#, BouncyCastle và khóa RSA đã nhập - Ví dụ về Python hoạt động và mẫu C# mã không hoạt động bên trong

RSACryptoServiceProvider.VerifyHash() luôn trả về false trên một ví dụ phù hợp với tôi bằng Python và M2Crypto.

Tôi đã xác minh rằng chữ ký băm giống hệt nhau giữa ví dụ làm việc và ví dụ C# và nó ở đó tôi bị kẹt. Tôi cảm thấy tôi thiếu một số chi tiết quan trọng.

Mã Python hoạt động và mã C# không hoạt động theo sau.

Chìa khóa được tạo ra với

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

mã Python (làm việc):

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# code (verifyhash() trả về 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); 
     } 
    } 
} 

Tại thời điểm này tôi không biết làm thế nào để tiến hành và giúp đỡ bất kỳ sẽ được đánh giá rất nhiều.

Trả lời

2

Đã xảy ra sự cố với cách bạn đang xây dựng lại khóa riêng tư/công khai. Rõ ràng trong python bạn cần chú ý để làm điều đó.

Tôi tạo phím mới xác minh (trong một định dạng khác nhau) sử dụng mã này:

private static void GenerateKeys(out string forPubKey, out string forPrivKey) 
     { 
      GenerateKeys(out forPubKey, out forPrivKey, 2048, 65537, 80); 
     } 

     /// <summary> 
     /// 
     /// </summary> 
     /// <param name="forPubKey"></param> 
     /// <param name="forPrivKey"></param> 
     /// <param name="keyStrength">1024, 2048,4096</param> 
     /// <param name="exponent">Typically a fermat number 3, 5, 17, 257, 65537, 4294967297, 18446744073709551617,</param> 
     /// <param name="certaninty">Should be 80 or higher depending on Key strength number (exponent)</param> 
     private static void GenerateKeys(out string forPubKey, out string forPrivKey, int keyStrength, int exponent, int certaninty) 
     { 
      // Create key 
      RsaKeyPairGenerator generator = new RsaKeyPairGenerator(); 

      /* 
      * This value should be a Fermat number. 0x10001 (F4) is current recommended value. 3 (F1) is known to be safe also. 
      * 3, 5, 17, 257, 65537, 4294967297, 18446744073709551617, 
      * 
      * Practically speaking, Windows does not tolerate public exponents which do not fit in a 32-bit unsigned integer. Using e=3 or e=65537 works "everywhere". 
      */ 
      BigInteger exponentBigInt = new BigInteger(exponent.ToString()); 

      var param = new RsaKeyGenerationParameters(
       exponentBigInt, // new BigInteger("10001", 16) publicExponent 
       new SecureRandom(), // SecureRandom.getInstance("SHA1PRNG"),//prng 
       keyStrength, //strength 
       certaninty);//certainty 
      generator.Init(param); 
      AsymmetricCipherKeyPair keyPair = generator.GenerateKeyPair(); 

      // Save to export format 
      SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public); 
      byte[] ret = info.GetEncoded(); 
      forPubKey = Convert.ToBase64String(ret); 

      // EncryptedPrivateKeyInfo asdf = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
      // DerObjectIdentifier.Ber,,,keyPair.Private); 

      //// demonstration: how to serialise option 1 
      //TextWriter textWriter = new StringWriter(); 
      //PemWriter pemWriter = new PemWriter(textWriter); 
      //pemWriter.WriteObject(keyPair); 
      //pemWriter.Writer.Flush(); 
      //string ret2 = textWriter.ToString(); 

      //// demonstration: how to serialise option 1 
      //TextReader tr = new StringReader(ret2); 
      //PemReader read = new PemReader(tr); 
      //AsymmetricCipherKeyPair something = (AsymmetricCipherKeyPair)read.ReadObject(); 

      //// demonstration: how to serialise option 2 (don't know how to deserailize) 
      //PrivateKeyInfo pKinfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private); 
      //byte[] privRet = pKinfo.GetEncoded(); 
      //string forPrivKey2Test = Convert.ToBase64String(privRet); 



      PrivateKeyInfo pKinfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private); 
      byte[] privRet = pKinfo.GetEncoded(); 
      string forPrivKey2Test = Convert.ToBase64String(privRet); 

      forPrivKey = forPrivKey2Test; 
     } 

và sau đó quay trở lại chúng thành các đối tượng RSA như thế này:

// Private key 
    RsaPrivateCrtKeyParameters kparam = ConvertToRSAPrivateKey(privateKey); 
     RSAParameters p1 = DotNetUtilities.ToRSAParameters(kparam); 
     rsa = new RSACryptoServiceProvider(); 
     rsa.ImportParameters(p1); 

// Public key 
RsaKeyParameters kparam = ConvertToRSAPublicKey(publicKey); 
     RSAParameters p1 = DotNetUtilities.ToRSAParameters(kparam); 
     rsa = new RSACryptoServiceProvider(); 
     rsa.ImportParameters(p1); 
Các vấn đề liên quan