2012-03-22 8 views
7

Przełamuję to, co zostało z moich włosów, próbując uzyskać banalny przykład podpisywania i weryfikacji danych RSA z C# i BouncyCastle działa.Podpisywanie i weryfikacja RSA za pomocą C#, BouncyCastle i zaimportowanego klucza RSA - Przykład działania Pythona i niepracująca próbka kodu C# wewnątrz

RSACryptoServiceProvider.VerifyHash() zawsze zwraca wartość false w przykładzie, który działa dla mnie z Python i M2Crypto.

Sprawdziłem, że podpisy mieszające są identyczne między przykładem roboczym a przykładem C# i to tam utknąłem. Czuję, że brakuje mi kilku istotnych szczegółów.

Działający kod w języku Python i nie działający kod C#.

Klucz został wygenerowany z

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

kodu Pythona (robocza):

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# kodu (verifyhash() zwraca 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); 
     } 
    } 
} 

w tym momencie nie wiem, jak postępować, a każda pomoc będzie bardzo ceniona.

Odpowiedz

2

Coś jest nie tak z tym, jak ponownie tworzysz prywatny/publiczny klucz. Oczywiście w pytonie trzeba pamiętać, aby to zrobić.

stworzyłem nowe klucze, które weryfikują (w innym formacie) przy użyciu tego kodu:

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; 
     } 

a następnie zwrócił je z powrotem do obiektów RSA tak:

// 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); 
Powiązane problemy