2016-10-26 2 views
2

J'ai un code de cryptage hérité en C# et maintenant je dois faire le même cryptage en JavaScript. J'ai fait quelques recherches et essayé 3 bibliothèques différentes, mais je n'ai pas pu obtenir les mêmes résultats. La dernière bibliothèque que j'ai utilisée est CryptoJS et je dois comprendre pourquoi je reçois des résultats différents.Les méthodes de cryptage C# & JS retournent des résultats différents

Voici les extraits de code:

code C#:

text = "chocolate"; 

    PasswordHash = "hashhash"; 
    SaltKey = "saltsaltsaltsa"; 
    VIKey = "iviviviviviviviv"; 

    byte[] plainTextBytes = Encoding.UTF8.GetBytes(text); 

    byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256/8); 
    var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros }; 
    var encryptor = symmetricKey.CreateEncryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey)); 

    byte[] cipherTextBytes; 

    using (var memoryStream = new MemoryStream()) 
    { 
     using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) 
     { 
     cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); 
     cryptoStream.FlushFinalBlock(); 
     cipherTextBytes = memoryStream.ToArray(); 
     cryptoStream.Close(); 
     } 
     memoryStream.Close(); 
    } 
    var result = Convert.ToBase64String(cipherTextBytes); 

résultat ==> "8AbNsyyqHHfi/PEF/bbiew =="

code JavaScript:

pass = 'chocolate'; 
//Creating the Vector Key 
var iv = CryptoJS.enc.Utf8.parse('iviviviviviviviv'); 
//Encoding the Password in from UTF8 to byte array 
var passHash = CryptoJS.enc.Utf8.parse('hashhash'); 
//Encoding the Salt in from UTF8 to byte array 
var Salt = CryptoJS.enc.Utf8.parse("saltsaltsaltsa"); 

//Creating the key in PBKDF2 format to be used during the encryption 
var key128Bits1000Iterations = CryptoJS.PBKDF2(passHash, Salt, { keySize: 256/8, iterations: 1000 }); 

//Encrypting the string contained in cipherParams using the PBKDF2 key 
var encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(pass), key128Bits1000Iterations, { mode: CryptoJS.mode.CBC, iv: iv, padding: CryptoJS.pad.ZeroPadding }); 
var result = encrypted.ciphertext.toString(CryptoJS.enc.Base64); 

résultat = "dpgTA41PD yrM8ef9C1c8iA == "

+0

vous semblez utiliser 'Encoding.ASCII' en C# et 'CryptoJS.enc.Utf8' dans le JS ..? – stuartd

+0

@stuartd - pensé à ce sujet, même comportement pour ASCII et UTF8 dans un scénario donné – Niro

Répondre

0

Enfin obtenu une solution. Merci à Luke Park qui m'a informé que CryptoJS utilise une structure de 4 octets (mot).

Le problème qui a conduit à des résultats différents est que la taille de la clé est (apparemment) différente. En C# 256/8 est en réalité 32 octets, mais en CryptoJS, en utilisant 4 octets, 256/8 traduit pratiquement 128 octets longueur :(

Une fois que je change la taille de la clé dans l'extrait JS à 256/32 ((256/32) * 4 = 32), il vous a parfaitement fonctionné et écho mêmes résultats que la méthode de cryptage C#.

Merci à tous Nir

0

Le problème est avec vos sels PBKDF2. CryptoJS utilise un WordArray comme primitive pour stocker les sels. C'est-à-dire un tableau de valeurs de 32 bits. Où C# utilise des valeurs de 8 bits (évidemment, il s'agit d'un tableau byte).

Avis alors que, JS:

var Salt = CryptoJS.lib.WordArray.create([1, 2]); 

est en C#, le même que:

byte[] Salt = new byte[] { 0, 0, 0, 1, 0, 0, 0, 2 }; 

Vous pouvez démontrer en sortant ce qui suit dans JS:

var Salt = CryptoJS.lib.WordArray.create([1, 2]); 
console.log(Salt.toString(CryptoJS.enc.Base64)); 
-> AAAAAQAAAAI= 

CryptoJS n'aime pas que les cordes soient utilisées comme sels. Ça ne l'aime pas du tout. Vous ne devriez pas utiliser une chaîne ou une phrase comme le sel de toute façon, il devrait être généré aléatoirement et stocké à côté du hachage de mot de passe.

+0

C'est exactement ce que fait" CryptoJS.enc.Utf8.parse ": convertir la chaîne en sa représentation de tableau de mots – Niro

+0

Oui, donc le sel dans C# vs JS est différent. –

+0

Vous avez tort à ce sujet, les sels sont les mêmes. L'un est représenté en utilisant des octets et l'autre en utilisant des mots, mais les données sont exactement les mêmes. Cependant - vous m'avez donné une direction qui m'a conduit à une solution alors merci quand même :) – Niro