2010-10-15 21 views
1

Je dois chiffrer le texte (mot de passe spécifique) correctement afin qu'un tiers puisse le déchiffrer. Ils m'ont fourni la clé qu'ils utilisent pour déchiffrer et m'ont dit qu'ils vont le décrypter de leur côté avec OpenSSL.Utilisation de System.Security.Cryptography pour chiffrer le texte afin qu'il corresponde à OpenSSL

J'ai essayé d'obtenir le AESManaged, et les classes RijndaelManaged dans System.Security.Cryptography pour créer quelque chose qui est décryptable mais pas très réussi.

L'exemple OpenSSL pour le chiffrement offert était:

echo "mot de passe" | enc -base64 -AES-256-cbc -k "providedKey" -p -md SHA1

Je dois créer un CryptoStream qui est un chiffreur AES avec une taille de clé de 256, et un mode de chiffrement de Radio-Canada . Et puis base64 coder le tableau d'octets résultant. Cette partie est assez simple. Ce que je ne sais pas comment créer est la clé et je cherche un point dans la bonne direction.

J'ai remarqué que tous les décodeurs base64 de texte créés par ces paramètres dans OpenSSL ont démarré avec les mêmes 8 caractères "Salted__". Donc je devine que c'est le sel utilisé pour générer la clé.

Quelqu'un sait comment créer une clé SHA1 avec la clé privée et "Salted__"?

Je suis conscient du projet OpenSSL.Net pour envelopper la DLL OpenSSL mais je voudrais éviter d'aller dans cette voie si c'est possible.

Répondre

2

Merci à GregS's Point in the right direction, Il était assez facile de répliquer la génération de clé et vecteur initial qui se passait dans EVP_BytesToKey(). Fondamentalement, ils créent un tableau de 48 octets (tableau de 32 octets pour la clé et un tableau de 16 octets pour l'IV) et en utilisant SHA1 pour hacher la clé privée et les 8 octets de sel dans ce tampon. Le premier hachage est juste la clé privée et le sel et les hachages successifs sont le dernier hachage généré concaténé avec les octets de clé et de sel jusqu'à ce que le tableau de 48 octets soit rempli.

La clé est alors seulement les 32 premiers octets et l'IV est les 16 derniers octets. En utilisant la classe AESManaged de System.Security.Crytpography et la clé et IV dérivée de cette méthode, j'ai pu chiffrer mes mots de passe d'une manière que le tiers utilisant les bibliothèques OpenSSL pouvait déchiffrer.

Voici l'algorithme je dériver le vecteur clé et initial:

/// <summary> 
    /// Derives the key and IV. 
    /// </summary> 
    /// <param name="saltBytes">The salt bytes.</param> 
    /// <param name="privateKeyBytes">The private key bytes.</param> 
    /// <param name="iv">The iv.</param> 
    /// <returns>The Key</returns> 
    private static byte[] DeriveKeyAndIV(byte[] saltBytes, byte[] privateKeyBytes, out byte[] iv) 
    { 
     // we are creating a 16 byte initial vector and a 32 byte key 
     const int ivLength = 16; 
     iv = new byte[ivLength]; 
     const int keyLength = 32; 
     var key = new byte[keyLength]; 

     //SHA1 creates a 20 byte hash 
     const int hashLength = 20; 

     // container to store the hashed values 
     var keyContainer = new byte[keyLength + ivLength]; 

     // munge together the privateKey and salt 
     var privateKeyAndSalt = new byte[privateKeyBytes.Length + saltBytes.Length]; 
     Array.Copy(privateKeyBytes, privateKeyAndSalt, privateKeyBytes.Length); 
     Array.Copy(saltBytes, 0, privateKeyAndSalt, privateKeyBytes.Length, saltBytes.Length); 

     // use SHA1 crypto to match the -md SHA1 command line. 
     var sha1 = new SHA1CryptoServiceProvider(); 

     // hashtarget holds the successive hash's source bytes. 
     var hashtarget = new byte[hashLength + privateKeyAndSalt.Length]; 

     byte[] currentHash = null; 
     var bytesCopied = 0; 

     // do the hashing until we fill the container 
     while (bytesCopied < (ivLength + keyLength)) 
     { 
      // Hash(0) is an empty set so just concatenate private key and salt. 
      if (currentHash == null) 
      { 
       currentHash = sha1.ComputeHash(privateKeyAndSalt); 
      } 
      else 
      { 
       // successive hashes are done on Hash(prev) + private key + salt. 
       Array.Copy(currentHash, hashtarget, currentHash.Length); 
       Array.Copy(privateKeyAndSalt, 0, hashtarget, currentHash.Length, privateKeyAndSalt.Length); 
       currentHash = hashtarget; 
       currentHash = sha1.ComputeHash(currentHash); 
      } 
      var copyAmount = Math.Min(currentHash.Length, keyContainer.Length - bytesCopied); 
      Array.Copy(currentHash, 0, keyContainer, bytesCopied, copyAmount); 
      bytesCopied += copyAmount; 
     } 

     // split out bytes in the container. first 32 are key, last 16 are iv. 
     Array.Copy(keyContainer, 0, key, 0, key.Length); 
     Array.Copy(keyContainer, key.Length, iv, 0, iv.Length); 

     return key; 
    } 
1

J'ai tapoté un peu dans la source openssl appropriée (apps/enc.c), et je pense que openssl utilise une approche quelque peu propriétaire. J'avoue que j'étais trop paresseux pour comprendre tous les détails, mais ils sont là. Il semble que la chaîne ASCII "Salted__" suivie des 8 octets de sel aléatoires sont ajoutées au fichier. Une clé AES et un AES iv sont dérivé à partir du mot de passe et de sel en utilisant une méthode openssl nommée EVP_BytesToKey(). L'algorithme est décrit dans cette page de manuel. Dans le enc.csource code de la version 1.0.0a cette partie commence à la ligne 510.

Espérons que cela peut vous aider à démarrer.