2013-05-03 24 views
1

我想加密/解密敏感数据,如SSN,加密过程进行得很顺利,保存在DB看起来不错,检索看起来也不错,但是当我在解密数据的最后一步我收到错误消息:解密数据的长度无效。解密数据的长度是无效的rijndael c#sql

我创建了一个SQL Server表进行测试,其有一列用的尺寸保存数据,varbinary类型的500

这是数据看起来像在表:

enter image description here

现在这里是C#中的完整代码,用于加密数据,插入数据库,获取最后一条记录(测试)并解密。正如我所说的在解密步骤的最后一步中出现错误:

加密步骤

public byte[] EncryptStringToBytes(string plainText) 
{ 
      // Check arguments. 
      if (plainText == null || plainText.Length <= 0) 
       throw new ArgumentNullException("plainText");   
      byte[] encrypted; 
      // Create an RijndaelManaged object 
      // with the specified key and IV. 
      using (RijndaelManaged rijAlg = new RijndaelManaged()) 
      { 
       rijAlg.Mode = CipherMode.CBC; 
       rijAlg.Padding = PaddingMode.PKCS7; 
       string keyStr = "cGFzc3dvcmQAAAAAAAAAAA=="; 
       string ivStr = "cGFzc3dvcmQAAAAAAAAAAA=="; 
       byte[] ivArr = Convert.FromBase64String(keyStr); 
       byte[] keyArr = Convert.FromBase64String(ivStr); 
       rijAlg.Key = keyArr; 
       rijAlg.KeySize = 256; 
       rijAlg.BlockSize = 128; 
       rijAlg.IV = ivArr; 

       // Create a decrytor to perform the stream transform. 
       ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV); 

       // Create the streams used for encryption. 
       using (MemoryStream msEncrypt = new MemoryStream()) 
       { 
        using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 
        { 
         using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) 
         { 
          //Write all data to the stream. 
          swEncrypt.Write(plainText); 
         } 
         encrypted = msEncrypt.ToArray(); 
         SaveData(encrypted); 
        } 
       } 
      } 
      // Return the encrypted bytes from the memory stream. 
      return encrypted; 
     } 

将数据保存到数据库

public void SaveData(byte[] cipherText) { 
    string queryStmt = "INSERT INTO TestSSN(SSN) VALUES(@Content)"; 

    using (SqlConnection _con = new SqlConnection(ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString)) 
    using (SqlCommand _cmd = new SqlCommand(queryStmt, _con)) 
    { 
     SqlParameter param = _cmd.Parameters.Add("@Content", SqlDbType.VarBinary); 
     param.Value = cipherText; 

     _con.Open(); 
     _cmd.ExecuteNonQuery(); 
     _con.Close(); 
    } 
    GetSSNData(1); } 

从数据库获取数据

public byte[] GetSSNData(int id) 
{ 
    byte[] cipherData = new byte[500]; 
    string queryStmt = "SELECT SSN FROM TestSSN WHERE ID=7"; 

    using (SqlConnection _con = new SqlConnection(ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString)) 
    using (SqlCommand _cmd = new SqlCommand(queryStmt, _con)) 
    {    
      _con.Open(); 
      SqlDataReader rdr = _cmd.ExecuteReader(); 

      if (rdr.HasRows) 
      { 
       while (rdr.Read()) 
       { 
        cipherData = Encoding.ASCII.GetBytes(rdr[0].ToString()); 
       } 
      } 
      _con.Close(); 
    } 
    string roundtrip = DecryptStringFromBytes(cipherData);   
    return cipherData; 
} 

试图解密数据(你会注意到两种不同的解密方式,但我会得到这些他们俩的消息)

static string DecryptStringFromBytes(byte[] cipherText) 
{ 
    // Check arguments. 
    if (cipherText == null || cipherText.Length <= 0) 
     throw new ArgumentNullException("cipherText");   

    // Declare the string used to hold 
    // the decrypted text. 
    string plaintext = null; 

    // Create an RijndaelManaged object 
    // with the specified key and IV. 
    using (RijndaelManaged rijAlg = new RijndaelManaged()) 
    { 
     rijAlg.Mode = CipherMode.CBC; 
     rijAlg.Padding = PaddingMode.PKCS7; 
     string keyStr = "cGFzc3dvcmQAAAAAAAAAAA=="; 
     string ivStr = "cGFzc3dvcmQAAAAAAAAAAA=="; 
     byte[] ivArr = Convert.FromBase64String(keyStr); 
     byte[] keyArr = Convert.FromBase64String(ivStr); 
     rijAlg.Key = keyArr; 
     rijAlg.KeySize = 256; 
     rijAlg.BlockSize = 128; 
     rijAlg.IV = ivArr; 
     // Create a decrytor to perform the stream transform. 
     ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV); 

     byte[] decryptedText = decryptor.TransformFinalBlock(cipherText, 0, cipherText.Length); 
     string decrpyted = ASCIIEncoding.UTF8.GetString(decryptedText);   

     // Create the streams used for decryption. 
     using (MemoryStream msDecrypt = new MemoryStream(cipherText)) 
     { 
      using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) 
      { 
       using (StreamReader srDecrypt = new StreamReader(csDecrypt)) 
       { 
        // byte[] decryptedText = decryptor.TransformFinalBlock(cipherText, 0, cipherText.Length); 
        // Read the decrypted bytes from the decrypting stream 
        // and place them in a string. 
        plaintext = srDecrypt.ReadToEnd(); 
       } 
      } 
     } 
    } 

    return plaintext; 
    } 

建议更多然后欢迎,我一直在与解密整天搏斗。

感谢,Laziale

+0

调试此问题的第一种方法是完全删除数据库代码。你能加密数据然后成功解密吗? – 2013-05-04 07:40:47

回答

0

检查你来自哪里,DB读取数据的地方:

cipherData = Encoding.ASCII.GetBytes(rdr[0].ToString()); 

如果rdr[0]byte阵列我不认为你会得到字节的字符串,可能你会得到“System.Byte []”。如果你会得到“0xFFAA” - Encoding.ASCII.GetBytes不会给你一个带有{0xFF,0xAA}数据的字节数组。您应该使用SqlDataReader.GetBytes来读取这些数据。

另外我想提醒你,SSN是敏感信息。你应该通知你的用户你要保存这些信息。如果您只需要这些信息来验证身份,您可以使用最后4位数字或散列。如果您没有真正的理由,请考虑不要保存SSN。

相关问题