2014-06-22 7 views
1

J'ai une classe minimale pour crypter et décrypter les objets DateTime sans un composant temporel. Le test ci-dessous fonctionnerait pour le 1er janvier 1988, mais échouerait pour le 1er janvier 1988, c.-à-d. la première itération passe mais la seconde échoue déjà.Chiffrement et déchiffrement de DateTime, System.Text.Encoding.Unicode.GetBytes et System.Text.Encoding.Unicode.GetString ne fonctionnant pas comme prévu?

Il semble que mon problème est définitivement en dehors du cryptage et du décryptage des octets. Lors du débogage de la deuxième itération (1988 2 janvier), crypté dans DateTime2EncryptedString a la valeur suivante:

{byte [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

Bien crypté dans EncryptedString2DateTime avec la chaîne de sortie DateTime2EncryptedString comme paramètre a la valeur suivante:

{byte [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

Le problème viendrait de mon incompréhension des octets à la chaîne (et vice versa) des opérations?

Le test

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

Et voici la petite classe utilitaire

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

Essayez de stocker des octets cryptés avec la méthode Convert.ToBase64String. Les octets cryptés peuvent contenir des séquences qui n'existent pas dans unicode. – Atomosk

+0

Cela a fonctionné, merci beaucoup. Pourriez-vous ajouter une réponse avec quelques détails supplémentaires pour que je puisse l'accepter? Ou un lien sur le concept de séquence dans les tableaux d'octets. – Jerome

+0

Plutôt que de chiffrer la représentation sous forme de chaîne, vous pouvez essayer de chiffrer la longue représentation de la propriété 'DateTime.Date' de la valeur' DateTime' d'origine que vous cryptez en appelant 'DateTime.ToBinary()'.Ensuite, vous n'aurez plus à vous préoccuper des problèmes d'encodage de chaînes ou de tout autre problème pouvant survenir lors de l'utilisation de méthodes de formatage, telles que les problèmes de représentation basés sur la localisation. –

Répondre

1

Pas toutes les séquences d'octets sont valides dans unicode. System.Text.Encoding.Unicode.GetString ignore de telles séquences. Base64 chaînes a été conçu pour convertir n'importe quelle séquence d'octets en chaîne. En .net, vous travaillez avec des chaînes base64 via la classe Convert via des méthodes telles que ToBase64String(Byte[]) et FromBase64String(string).

Questions connexes