Reproducing JS PBKDF2 Hash in C#
up vote
2
down vote
favorite
I had to implement some new security features for an Existing Database. They used to hash passwords on the side of the client with a salt from the DB. They used this code to hash the passwords before sending them to the server:
var hash = CryptoJS.PBKDF2(password, USER_SALT, {
keySize: 4,
iterations: 1000
});
Now as you can already guess, this is highly insecure, cause an attacker gets the PW as if it was sent in plain text if the user gets the Salt from the server and the hasing is done client side. That's why I need to do it server side.
Now the DB has several thousand entries with hashed passwords of users, that use this DB. I tried implementing a similar method in C# with many references from the internet, but I couldn't get the same Hashes as stored in the DB.
public static string HashPassword(string password, string salt)
{
byte saltBytes = Encoding.UTF8.GetBytes(salt);
using (var rfc2898 = new Rfc2898DeriveBytes(password, saltBytes, 1000))
{
byte hash = rfc2898.GetBytes(16);
string hashString = string.Empty;
foreach (byte x in hash)
{
hashString += String.Format("{0:x2}", x);
}
return hashString;
}
}
This was the method I used. I wanted to reproduce the keysize 4 of CryptoJS so I'd get 4x = 32 digit long password hashes. I do get them, but they're different than the ones I would get in JS with CryptoJS.
Does anyone know how to get the same result as the CryptoJS version would? BEcause all passwords in the DB have been stored that way, it is crucial they are now generated the same way again only server side. (The Passwords are now encrypted against attacks).
javascript c# hash cryptography pbkdf2
add a comment |
up vote
2
down vote
favorite
I had to implement some new security features for an Existing Database. They used to hash passwords on the side of the client with a salt from the DB. They used this code to hash the passwords before sending them to the server:
var hash = CryptoJS.PBKDF2(password, USER_SALT, {
keySize: 4,
iterations: 1000
});
Now as you can already guess, this is highly insecure, cause an attacker gets the PW as if it was sent in plain text if the user gets the Salt from the server and the hasing is done client side. That's why I need to do it server side.
Now the DB has several thousand entries with hashed passwords of users, that use this DB. I tried implementing a similar method in C# with many references from the internet, but I couldn't get the same Hashes as stored in the DB.
public static string HashPassword(string password, string salt)
{
byte saltBytes = Encoding.UTF8.GetBytes(salt);
using (var rfc2898 = new Rfc2898DeriveBytes(password, saltBytes, 1000))
{
byte hash = rfc2898.GetBytes(16);
string hashString = string.Empty;
foreach (byte x in hash)
{
hashString += String.Format("{0:x2}", x);
}
return hashString;
}
}
This was the method I used. I wanted to reproduce the keysize 4 of CryptoJS so I'd get 4x = 32 digit long password hashes. I do get them, but they're different than the ones I would get in JS with CryptoJS.
Does anyone know how to get the same result as the CryptoJS version would? BEcause all passwords in the DB have been stored that way, it is crucial they are now generated the same way again only server side. (The Passwords are now encrypted against attacks).
javascript c# hash cryptography pbkdf2
stackoverflow.com/questions/11412882/…
– Dmitry Bychenko
Nov 8 at 14:42
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I had to implement some new security features for an Existing Database. They used to hash passwords on the side of the client with a salt from the DB. They used this code to hash the passwords before sending them to the server:
var hash = CryptoJS.PBKDF2(password, USER_SALT, {
keySize: 4,
iterations: 1000
});
Now as you can already guess, this is highly insecure, cause an attacker gets the PW as if it was sent in plain text if the user gets the Salt from the server and the hasing is done client side. That's why I need to do it server side.
Now the DB has several thousand entries with hashed passwords of users, that use this DB. I tried implementing a similar method in C# with many references from the internet, but I couldn't get the same Hashes as stored in the DB.
public static string HashPassword(string password, string salt)
{
byte saltBytes = Encoding.UTF8.GetBytes(salt);
using (var rfc2898 = new Rfc2898DeriveBytes(password, saltBytes, 1000))
{
byte hash = rfc2898.GetBytes(16);
string hashString = string.Empty;
foreach (byte x in hash)
{
hashString += String.Format("{0:x2}", x);
}
return hashString;
}
}
This was the method I used. I wanted to reproduce the keysize 4 of CryptoJS so I'd get 4x = 32 digit long password hashes. I do get them, but they're different than the ones I would get in JS with CryptoJS.
Does anyone know how to get the same result as the CryptoJS version would? BEcause all passwords in the DB have been stored that way, it is crucial they are now generated the same way again only server side. (The Passwords are now encrypted against attacks).
javascript c# hash cryptography pbkdf2
I had to implement some new security features for an Existing Database. They used to hash passwords on the side of the client with a salt from the DB. They used this code to hash the passwords before sending them to the server:
var hash = CryptoJS.PBKDF2(password, USER_SALT, {
keySize: 4,
iterations: 1000
});
Now as you can already guess, this is highly insecure, cause an attacker gets the PW as if it was sent in plain text if the user gets the Salt from the server and the hasing is done client side. That's why I need to do it server side.
Now the DB has several thousand entries with hashed passwords of users, that use this DB. I tried implementing a similar method in C# with many references from the internet, but I couldn't get the same Hashes as stored in the DB.
public static string HashPassword(string password, string salt)
{
byte saltBytes = Encoding.UTF8.GetBytes(salt);
using (var rfc2898 = new Rfc2898DeriveBytes(password, saltBytes, 1000))
{
byte hash = rfc2898.GetBytes(16);
string hashString = string.Empty;
foreach (byte x in hash)
{
hashString += String.Format("{0:x2}", x);
}
return hashString;
}
}
This was the method I used. I wanted to reproduce the keysize 4 of CryptoJS so I'd get 4x = 32 digit long password hashes. I do get them, but they're different than the ones I would get in JS with CryptoJS.
Does anyone know how to get the same result as the CryptoJS version would? BEcause all passwords in the DB have been stored that way, it is crucial they are now generated the same way again only server side. (The Passwords are now encrypted against attacks).
javascript c# hash cryptography pbkdf2
javascript c# hash cryptography pbkdf2
asked Nov 8 at 14:10
VanDeath
1891217
1891217
stackoverflow.com/questions/11412882/…
– Dmitry Bychenko
Nov 8 at 14:42
add a comment |
stackoverflow.com/questions/11412882/…
– Dmitry Bychenko
Nov 8 at 14:42
stackoverflow.com/questions/11412882/…
– Dmitry Bychenko
Nov 8 at 14:42
stackoverflow.com/questions/11412882/…
– Dmitry Bychenko
Nov 8 at 14:42
add a comment |
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
Using a JSFiddle for CryptoJS/PBKDF2 (though I had to correct the CDN links), whose relevant code is
var password = $("[name='password']").val();
var iterations = 1000;
// sizes must be a multiple of 32
var keySize = 128;
var ivSize = 128;
var salt = CryptoJS.lib.WordArray.random(128/8);
$("#salt").html(salt.toString(CryptoJS.enc.Base64));
$("#iter").html(iterations);
$("#keysize").html(keySize);
$("#ivsize").html(ivSize);
var output = CryptoJS.PBKDF2(password, salt, {
keySize: (keySize+ivSize)/32,
iterations: iterations
});
// the underlying words arrays might have more content than was asked: remove insignificant words
output.clamp();
var key = CryptoJS.lib.WordArray.create(output.words.slice(0, keySize/32));
var iv = CryptoJS.lib.WordArray.create(output.words.slice(keySize/32));
$("#hasher").html("SHA1");
$("#key").html(key.toString(CryptoJS.enc.Base64));
$("#iv").html(iv.toString(CryptoJS.enc.Base64));
I got as one sample input/output "hello"
with a (base64) salt of 0CD1HGFdkclqcWG5aV+rvw==
(and the default hash algorithm, with the specified 1000 iterations and 32+32 byte outputs); that produced tRczLRRuFy/zFiPn1PBKmQ==
/ dhyeE+0Dd9avSJbM/4TcNw==
.
The following C# discovery code was then utilized:
string password = "hello";
byte salt = Convert.FromBase64String("0CD1HGFdkclqcWG5aV+rvw==");
int iterations = 1000;
using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA1))
{
Console.WriteLine("UTF-8 / SHA-1");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA256))
{
Console.WriteLine("UTF-8 / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
byte utf16 = Encoding.Unicode.GetBytes(password);
using (var pbkdf2 = new Rfc2898DeriveBytes(utf16, salt, iterations, HashAlgorithmName.SHA1))
{
Console.WriteLine("UTF-16LE / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
using (var pbkdf2 = new Rfc2898DeriveBytes(utf16, salt, iterations, HashAlgorithmName.SHA256))
{
Console.WriteLine("UTF-16LE / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
with an output of
UTF-8 / SHA-1
tRczLRRuFy/zFiPn1PBKmQ== dhyeE+0Dd9avSJbM/4TcNw==
UTF-8 / SHA-2-256
lkBtILt+xDNEQrX0aWUk3Q== ouOiijCw5sjfMcJo9YZ4Ug==
UTF-16LE / SHA-2-256
1T2gJFFECc5AnpvoiFrBwg== rmHsTuOQdM5YDsmzklMEUQ==
UTF-16LE / SHA-2-256
G4/Ik5vZAd2l8kwq45BKaw== Iqy61Eaf8jmoxO2TpA+rkg==
Conclusion: CryptoJS.PBKDF2 is using SHA-1 and UTF-8, which means that the most likely problem is that you're loading in the wrong salt if you're not getting the same answer. If it's not a UTF-8 string it's probably either hexadecimal data or base64 (but that depends completely on your usage, there's no "the right answer is" here, as the salt is "just bytes").
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
Using a JSFiddle for CryptoJS/PBKDF2 (though I had to correct the CDN links), whose relevant code is
var password = $("[name='password']").val();
var iterations = 1000;
// sizes must be a multiple of 32
var keySize = 128;
var ivSize = 128;
var salt = CryptoJS.lib.WordArray.random(128/8);
$("#salt").html(salt.toString(CryptoJS.enc.Base64));
$("#iter").html(iterations);
$("#keysize").html(keySize);
$("#ivsize").html(ivSize);
var output = CryptoJS.PBKDF2(password, salt, {
keySize: (keySize+ivSize)/32,
iterations: iterations
});
// the underlying words arrays might have more content than was asked: remove insignificant words
output.clamp();
var key = CryptoJS.lib.WordArray.create(output.words.slice(0, keySize/32));
var iv = CryptoJS.lib.WordArray.create(output.words.slice(keySize/32));
$("#hasher").html("SHA1");
$("#key").html(key.toString(CryptoJS.enc.Base64));
$("#iv").html(iv.toString(CryptoJS.enc.Base64));
I got as one sample input/output "hello"
with a (base64) salt of 0CD1HGFdkclqcWG5aV+rvw==
(and the default hash algorithm, with the specified 1000 iterations and 32+32 byte outputs); that produced tRczLRRuFy/zFiPn1PBKmQ==
/ dhyeE+0Dd9avSJbM/4TcNw==
.
The following C# discovery code was then utilized:
string password = "hello";
byte salt = Convert.FromBase64String("0CD1HGFdkclqcWG5aV+rvw==");
int iterations = 1000;
using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA1))
{
Console.WriteLine("UTF-8 / SHA-1");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA256))
{
Console.WriteLine("UTF-8 / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
byte utf16 = Encoding.Unicode.GetBytes(password);
using (var pbkdf2 = new Rfc2898DeriveBytes(utf16, salt, iterations, HashAlgorithmName.SHA1))
{
Console.WriteLine("UTF-16LE / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
using (var pbkdf2 = new Rfc2898DeriveBytes(utf16, salt, iterations, HashAlgorithmName.SHA256))
{
Console.WriteLine("UTF-16LE / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
with an output of
UTF-8 / SHA-1
tRczLRRuFy/zFiPn1PBKmQ== dhyeE+0Dd9avSJbM/4TcNw==
UTF-8 / SHA-2-256
lkBtILt+xDNEQrX0aWUk3Q== ouOiijCw5sjfMcJo9YZ4Ug==
UTF-16LE / SHA-2-256
1T2gJFFECc5AnpvoiFrBwg== rmHsTuOQdM5YDsmzklMEUQ==
UTF-16LE / SHA-2-256
G4/Ik5vZAd2l8kwq45BKaw== Iqy61Eaf8jmoxO2TpA+rkg==
Conclusion: CryptoJS.PBKDF2 is using SHA-1 and UTF-8, which means that the most likely problem is that you're loading in the wrong salt if you're not getting the same answer. If it's not a UTF-8 string it's probably either hexadecimal data or base64 (but that depends completely on your usage, there's no "the right answer is" here, as the salt is "just bytes").
add a comment |
up vote
1
down vote
accepted
Using a JSFiddle for CryptoJS/PBKDF2 (though I had to correct the CDN links), whose relevant code is
var password = $("[name='password']").val();
var iterations = 1000;
// sizes must be a multiple of 32
var keySize = 128;
var ivSize = 128;
var salt = CryptoJS.lib.WordArray.random(128/8);
$("#salt").html(salt.toString(CryptoJS.enc.Base64));
$("#iter").html(iterations);
$("#keysize").html(keySize);
$("#ivsize").html(ivSize);
var output = CryptoJS.PBKDF2(password, salt, {
keySize: (keySize+ivSize)/32,
iterations: iterations
});
// the underlying words arrays might have more content than was asked: remove insignificant words
output.clamp();
var key = CryptoJS.lib.WordArray.create(output.words.slice(0, keySize/32));
var iv = CryptoJS.lib.WordArray.create(output.words.slice(keySize/32));
$("#hasher").html("SHA1");
$("#key").html(key.toString(CryptoJS.enc.Base64));
$("#iv").html(iv.toString(CryptoJS.enc.Base64));
I got as one sample input/output "hello"
with a (base64) salt of 0CD1HGFdkclqcWG5aV+rvw==
(and the default hash algorithm, with the specified 1000 iterations and 32+32 byte outputs); that produced tRczLRRuFy/zFiPn1PBKmQ==
/ dhyeE+0Dd9avSJbM/4TcNw==
.
The following C# discovery code was then utilized:
string password = "hello";
byte salt = Convert.FromBase64String("0CD1HGFdkclqcWG5aV+rvw==");
int iterations = 1000;
using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA1))
{
Console.WriteLine("UTF-8 / SHA-1");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA256))
{
Console.WriteLine("UTF-8 / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
byte utf16 = Encoding.Unicode.GetBytes(password);
using (var pbkdf2 = new Rfc2898DeriveBytes(utf16, salt, iterations, HashAlgorithmName.SHA1))
{
Console.WriteLine("UTF-16LE / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
using (var pbkdf2 = new Rfc2898DeriveBytes(utf16, salt, iterations, HashAlgorithmName.SHA256))
{
Console.WriteLine("UTF-16LE / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
with an output of
UTF-8 / SHA-1
tRczLRRuFy/zFiPn1PBKmQ== dhyeE+0Dd9avSJbM/4TcNw==
UTF-8 / SHA-2-256
lkBtILt+xDNEQrX0aWUk3Q== ouOiijCw5sjfMcJo9YZ4Ug==
UTF-16LE / SHA-2-256
1T2gJFFECc5AnpvoiFrBwg== rmHsTuOQdM5YDsmzklMEUQ==
UTF-16LE / SHA-2-256
G4/Ik5vZAd2l8kwq45BKaw== Iqy61Eaf8jmoxO2TpA+rkg==
Conclusion: CryptoJS.PBKDF2 is using SHA-1 and UTF-8, which means that the most likely problem is that you're loading in the wrong salt if you're not getting the same answer. If it's not a UTF-8 string it's probably either hexadecimal data or base64 (but that depends completely on your usage, there's no "the right answer is" here, as the salt is "just bytes").
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
Using a JSFiddle for CryptoJS/PBKDF2 (though I had to correct the CDN links), whose relevant code is
var password = $("[name='password']").val();
var iterations = 1000;
// sizes must be a multiple of 32
var keySize = 128;
var ivSize = 128;
var salt = CryptoJS.lib.WordArray.random(128/8);
$("#salt").html(salt.toString(CryptoJS.enc.Base64));
$("#iter").html(iterations);
$("#keysize").html(keySize);
$("#ivsize").html(ivSize);
var output = CryptoJS.PBKDF2(password, salt, {
keySize: (keySize+ivSize)/32,
iterations: iterations
});
// the underlying words arrays might have more content than was asked: remove insignificant words
output.clamp();
var key = CryptoJS.lib.WordArray.create(output.words.slice(0, keySize/32));
var iv = CryptoJS.lib.WordArray.create(output.words.slice(keySize/32));
$("#hasher").html("SHA1");
$("#key").html(key.toString(CryptoJS.enc.Base64));
$("#iv").html(iv.toString(CryptoJS.enc.Base64));
I got as one sample input/output "hello"
with a (base64) salt of 0CD1HGFdkclqcWG5aV+rvw==
(and the default hash algorithm, with the specified 1000 iterations and 32+32 byte outputs); that produced tRczLRRuFy/zFiPn1PBKmQ==
/ dhyeE+0Dd9avSJbM/4TcNw==
.
The following C# discovery code was then utilized:
string password = "hello";
byte salt = Convert.FromBase64String("0CD1HGFdkclqcWG5aV+rvw==");
int iterations = 1000;
using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA1))
{
Console.WriteLine("UTF-8 / SHA-1");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA256))
{
Console.WriteLine("UTF-8 / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
byte utf16 = Encoding.Unicode.GetBytes(password);
using (var pbkdf2 = new Rfc2898DeriveBytes(utf16, salt, iterations, HashAlgorithmName.SHA1))
{
Console.WriteLine("UTF-16LE / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
using (var pbkdf2 = new Rfc2898DeriveBytes(utf16, salt, iterations, HashAlgorithmName.SHA256))
{
Console.WriteLine("UTF-16LE / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
with an output of
UTF-8 / SHA-1
tRczLRRuFy/zFiPn1PBKmQ== dhyeE+0Dd9avSJbM/4TcNw==
UTF-8 / SHA-2-256
lkBtILt+xDNEQrX0aWUk3Q== ouOiijCw5sjfMcJo9YZ4Ug==
UTF-16LE / SHA-2-256
1T2gJFFECc5AnpvoiFrBwg== rmHsTuOQdM5YDsmzklMEUQ==
UTF-16LE / SHA-2-256
G4/Ik5vZAd2l8kwq45BKaw== Iqy61Eaf8jmoxO2TpA+rkg==
Conclusion: CryptoJS.PBKDF2 is using SHA-1 and UTF-8, which means that the most likely problem is that you're loading in the wrong salt if you're not getting the same answer. If it's not a UTF-8 string it's probably either hexadecimal data or base64 (but that depends completely on your usage, there's no "the right answer is" here, as the salt is "just bytes").
Using a JSFiddle for CryptoJS/PBKDF2 (though I had to correct the CDN links), whose relevant code is
var password = $("[name='password']").val();
var iterations = 1000;
// sizes must be a multiple of 32
var keySize = 128;
var ivSize = 128;
var salt = CryptoJS.lib.WordArray.random(128/8);
$("#salt").html(salt.toString(CryptoJS.enc.Base64));
$("#iter").html(iterations);
$("#keysize").html(keySize);
$("#ivsize").html(ivSize);
var output = CryptoJS.PBKDF2(password, salt, {
keySize: (keySize+ivSize)/32,
iterations: iterations
});
// the underlying words arrays might have more content than was asked: remove insignificant words
output.clamp();
var key = CryptoJS.lib.WordArray.create(output.words.slice(0, keySize/32));
var iv = CryptoJS.lib.WordArray.create(output.words.slice(keySize/32));
$("#hasher").html("SHA1");
$("#key").html(key.toString(CryptoJS.enc.Base64));
$("#iv").html(iv.toString(CryptoJS.enc.Base64));
I got as one sample input/output "hello"
with a (base64) salt of 0CD1HGFdkclqcWG5aV+rvw==
(and the default hash algorithm, with the specified 1000 iterations and 32+32 byte outputs); that produced tRczLRRuFy/zFiPn1PBKmQ==
/ dhyeE+0Dd9avSJbM/4TcNw==
.
The following C# discovery code was then utilized:
string password = "hello";
byte salt = Convert.FromBase64String("0CD1HGFdkclqcWG5aV+rvw==");
int iterations = 1000;
using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA1))
{
Console.WriteLine("UTF-8 / SHA-1");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA256))
{
Console.WriteLine("UTF-8 / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
byte utf16 = Encoding.Unicode.GetBytes(password);
using (var pbkdf2 = new Rfc2898DeriveBytes(utf16, salt, iterations, HashAlgorithmName.SHA1))
{
Console.WriteLine("UTF-16LE / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
using (var pbkdf2 = new Rfc2898DeriveBytes(utf16, salt, iterations, HashAlgorithmName.SHA256))
{
Console.WriteLine("UTF-16LE / SHA-2-256");
Console.Write(Convert.ToBase64String(pbkdf2.GetBytes(16)));
Console.Write(' ');
Console.WriteLine(Convert.ToBase64String(pbkdf2.GetBytes(16)));
}
with an output of
UTF-8 / SHA-1
tRczLRRuFy/zFiPn1PBKmQ== dhyeE+0Dd9avSJbM/4TcNw==
UTF-8 / SHA-2-256
lkBtILt+xDNEQrX0aWUk3Q== ouOiijCw5sjfMcJo9YZ4Ug==
UTF-16LE / SHA-2-256
1T2gJFFECc5AnpvoiFrBwg== rmHsTuOQdM5YDsmzklMEUQ==
UTF-16LE / SHA-2-256
G4/Ik5vZAd2l8kwq45BKaw== Iqy61Eaf8jmoxO2TpA+rkg==
Conclusion: CryptoJS.PBKDF2 is using SHA-1 and UTF-8, which means that the most likely problem is that you're loading in the wrong salt if you're not getting the same answer. If it's not a UTF-8 string it's probably either hexadecimal data or base64 (but that depends completely on your usage, there's no "the right answer is" here, as the salt is "just bytes").
answered Nov 9 at 17:42
bartonjs
12.7k12052
12.7k12052
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53209486%2freproducing-js-pbkdf2-hash-in-c-sharp%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
stackoverflow.com/questions/11412882/…
– Dmitry Bychenko
Nov 8 at 14:42