2013-05-03 46 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。

相關問題