2014-06-22 44 views
1

我有一個最小類來加密和解密沒有時間組件的DateTime對象。下面的測試適用於1988年1月1日,但1988年1月2日失敗,即。第一次迭代通過但第二次失敗。DateTime加密和解密,System.Text.Encoding.Unicode.GetBytes和System.Text.Encoding.Unicode.GetString不按預期工作?

看來我的問題絕對是在字節的加密和解密之外。當在DateTime2EncryptedString調試加密第二次迭代(1988 1月2日),具有以下值:

{字節[16]} [0]:147 [1]:1 [2] :22 [3]:250 [4]:74 [5]:227 [6]:225 [7]:91 [8]:157 [9]:202 [10]:138 [11]:246 [12]:91 [13]:131 [14]:42 [15]:217

雖然加密EncryptedString2DateTimeDateTime2EncryptedString的輸出字符串作爲參數具有以下值:

{字節[16]} [0]:147 [1]:1 [2]:22 [3]:250 [4]:74 [5]:227 [6]:225 [7]:91 [8]:157 [9]:202 [10]:138 [11]:246 [12]:91 [13]:131 [14]:253 [ 15]:255

這個問題來自我誤解字符串(反之亦然)的操作?

測試

 public void Test1() 
     { 
      for (int year = 1988; year < 2010; year++) 
      { 
       for (int month = 1; month < 12; month++) 
       { 
        for (int day = 1; day < 28; day++) 
        { 
         var dt = new DateTime(year, month, day); 
         TestDate(dt); 
        } 
       } 
      } 
     } 

     private void TestDate(DateTime dt) 
     { 
      var encryptedString = DateEncryption.DateTime2EncryptedString(dt); 
      var output = DateEncryption.EncryptedString2DateTime(encryptedString); 
      Assert.AreEqual(dt, output); 
     } 

這裏是小工具類

public static class DateEncryption 
{ 
    private static readonly byte[] Key = new byte[] 
    { 
     32, 29, 124, 21, 92, 18, 28,34, 74, 85, 14, 91, 51, 28, 73, 49, 54, 99, 1, 192, 211, 253, 251, 252, 
     237, 142, 161, 178, 199, 208, 97, 98 
    }; 
    private static readonly byte[] Iv = new byte[] { 19, 28, 33, 77, 131, 178, 192, 200, 215, 148, 247, 192, 184, 127, 3, 7}; 

    private static byte[] Decrypt(byte[] cipherData) 
    { 
     byte[] decryptedData; 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      using (Rijndael alg = Rijndael.Create()) 
      { 
       alg.Padding = PaddingMode.None; 
       alg.Key = Key; 
       alg.IV = Iv; 
       using (CryptoStream cs = new CryptoStream(ms, 
        alg.CreateDecryptor(), CryptoStreamMode.Write)) 
       { 
        cs.Write(cipherData, 0, cipherData.Length); 
       } 
       decryptedData = ms.ToArray(); 
      } 
     } 
     return decryptedData; 
    } 

    private static byte[] Encrypt(byte[] clearData) 
    { 
     byte[] encryptedData; 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      using (Rijndael alg = Rijndael.Create()) 
      { 
       alg.Padding = PaddingMode.None; 
       alg.Key = Key; 
       alg.IV = Iv; 
       using (CryptoStream cs = new CryptoStream(ms, 
        alg.CreateEncryptor(), CryptoStreamMode.Write)) 
       { 
        cs.Write(clearData, 0, clearData.Length); 
       } 
       encryptedData = ms.ToArray(); 
      } 
     } 
     return encryptedData; 
    } 


    #region DateTimeEncryption 

    public static string DateTime2EncryptedString(DateTime dt) 
    { 
     var dt2str = string.Format("{0:D4}{1:D2}{2:D2}", dt.Year, dt.Month, dt.Day); 
     var str2bytes = System.Text.Encoding.Unicode.GetBytes(dt2str); 
     var encrypted = Encrypt(str2bytes); 
     return System.Text.Encoding.Unicode.GetString(encrypted); 
    } 

    public static DateTime EncryptedString2DateTime(string s) 
    { 
     var encrypted = System.Text.Encoding.Unicode.GetBytes(s); 
     var decrypted = Decrypt(encrypted); 
     var bytes2str = System.Text.Encoding.Unicode.GetString(decrypted); 
     return new DateTime(int.Parse(bytes2str.Substring(0, 4)), 
      int.Parse(bytes2str.Substring(4, 2)), 
      int.Parse(bytes2str.Substring(6, 2))); 
    } 

    #endregion 
} 
+1

嘗試使用Convert.ToBase64String方法存儲加密的字節。加密的字節可以包含序列,這在unicode中不存在。 – Atomosk

+0

工作,非常感謝。你可以添加一些答案和更多細節,以便我可以接受它嗎?或者關於字節數組中序列概念的一些鏈接。 – Jerome

+0

您可以嘗試通過調用'DateTime.ToBinary()'來加密您正在加密的原始'DateTime'值的'DateTime.Date'屬性的長表示形式,而不是加密字符串表示形式。然後,您不必擔心字符串編碼問題或使用格式化方法可能產生的任何其他問題,例如基於本地化的表示問題。 –

回答

1

不是字節的每個序列爲Unicode有效。 System.Text.Encoding.Unicode.GetString忽略這樣的序列。 Base64字符串被設計爲轉換字符串中的任何字節序列。在.net中,您可以通過ToBase64String(Byte[])FromBase64String(string)等方法通過Convert類使用base64字符串。