2017-04-11 234 views
0

我的问题与2011年的一个表格Signing and verifying signatures with RSA C#非常相似。尽管如此,当我比较签名数据和原始消息时,我也会失败。请指出我的错误。C#使用RSA签名和验证签名。编码问题

代码:

public static void Main(string[] args) 
    {    

     //Generate a public/private key pair. 
     RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); 

     //Save the public key information to an RSAParameters structure. 
     RSAParameters RSAPublicKeyInfo = RSA.ExportParameters(false); 
     RSAParameters RSAPrivateKeyInfo = RSA.ExportParameters(true);  

     string message = "2017-04-10T09:37:35.351Z"; 

     string signedMessage = SignData(message, RSAPrivateKeyInfo); 

     bool success = VerifyData(message, signedMessage, RSAPublicKeyInfo); 

     Console.WriteLine($"success {success}"); 

     Console.ReadLine(); 
    } 

签名方法:

public static string SignData(string message, RSAParameters privateKey) 
    { 
     ASCIIEncoding byteConverter = new ASCIIEncoding(); 

     byte[] signedBytes; 

     using (var rsa = new RSACryptoServiceProvider()) 
     { 
      // Write the message to a byte array using ASCII as the encoding. 
      byte[] originalData = byteConverter.GetBytes(message);     

      try 
      { 
       // Import the private key used for signing the message 
       rsa.ImportParameters(privateKey); 

       // Sign the data, using SHA512 as the hashing algorithm 
       signedBytes = rsa.SignData(originalData, CryptoConfig.MapNameToOID("SHA512")); 
      } 
      catch (CryptographicException e) 
      { 
       Console.WriteLine(e.Message); 
       return null; 
      } 
      finally 
      { 
       // Set the keycontainer to be cleared when rsa is garbage collected. 
       rsa.PersistKeyInCsp = false; 
      } 
     } 
     // Convert the byte array back to a string message 
     return byteConverter.GetString(signedBytes); 
    } 

验证方法:

public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey) 
    { 
     bool success = false; 
     using (var rsa = new RSACryptoServiceProvider()) 
     { 
      ASCIIEncoding byteConverter = new ASCIIEncoding(); 

      byte[] bytesToVerify = byteConverter.GetBytes(originalMessage); 
      byte[] signedBytes = byteConverter.GetBytes(signedMessage); 

      try 
      { 
       rsa.ImportParameters(publicKey); 

       success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA512"), signedBytes); 
      } 
      catch (CryptographicException e) 
      { 
       Console.WriteLine(e.Message); 
      } 
      finally 
      { 
       rsa.PersistKeyInCsp = false; 
      } 
     } 
     return success; 
    } 

基本上问题是与串为byte []编码。我遇到了与ASCIIEncoding和UTF8Encoding相同的问题。

预先感谢您!

回答

2

您不能在编码消息上使用ASCIIEncoding,因为它包含无效ASCII字符的字节。存储编码消息的典型方法是使用base64字符串。

SignData,使用以下的字节数组编码为字符串:

return Convert.ToBase64String(signedBytes); 

VerifyData,使用下面的字符串后面进行解码,以相同的字节数组:

byte[] signedBytes = Convert.FromBase64String(signedMessage); 
+0

感谢您的及时答复!但是,我得到“System.FormatException:”输入不是有效的Base-64字符串,因为它包含非基本64字符,多于两个填充字符或填充字符中的非法字符。'“当我使用FromBase64String为消息“”2017-04-10T09:37:35.351Z“”。 –

+1

在验证之前是否有任何事情发生在字符串上?我用上面的2个更改运行了你的发布代码,它工作。 – msitt

+0

你是对的!我的糟糕之处在于,我还试图在签名之前对原始数据的Base64字符串执行字符串。 –