1

SSN などの機密データを暗号化/復号化しようとしています。暗号化プロセスはうまくいき、DB への保存もうまくいき、検索もうまくいくように見えますが、データを復号化する最後のステップにいるときに、エラー メッセージが表示されます: 長さ復号化するデータの数が無効です。

varbinaryサイズが 500のデータを保持するための 1 つの列を持つ、テスト用の SQL Server テーブルを作成しました。

テーブル内のデータは次のようになります。

ここに画像の説明を入力

これは、データの暗号化、データベースへの挿入、最後のレコードの取得 (テスト)、および復号化に使用される 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;
}

データの復号化を試みています (ここで復号化の 2 つの異なる方法に気付くでしょうが、どちらの方法でも同じメッセージが表示されます)

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

アドバイスを歓迎します。私は一日中復号化と戦っています。

ありがとう、ラツィアーレ

4

1 に答える 1

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 を保存しないことを検討してください。

于 2013-05-03T15:08:04.607 に答える