首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在PBKDF2中复制JS PBKDF2哈希

在PBKDF2中复制JS PBKDF2哈希
EN

Stack Overflow用户
提问于 2018-11-08 14:10:55
回答 1查看 908关注 0票数 3

我必须为一个现有的数据库实现一些新的安全特性。他们过去常常在客户端用DB的盐分散列密码。在将密码发送到服务器之前,他们使用此代码对密码进行散列:

代码语言:javascript
复制
var hash = CryptoJS.PBKDF2(password, USER_SALT, {
    keySize: 4,
    iterations: 1000
});

现在,您已经可以猜到,这是高度不安全的,因为攻击者获得的PW就好像它是以纯文本发送的,如果用户从服务器获得Salt,并且hasing是客户端完成的。这就是为什么我需要做服务器端。

现在DB有几千个条目,其中包含用户的散列密码,它们使用这个DB。我尝试在C#中实现一种类似的方法,其中有许多来自互联网的引用,但是我无法获得存储在DB中的相同的散列。

代码语言:javascript
复制
    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;
        }
    }

这就是我用的方法。我想复制CryptoJS的键大小4,所以我会得到4x = 32位长密码散列。我确实理解它们,但它们与我在CryptoJS中获得的JS不同。

有人知道如何获得与CryptoJS版本相同的结果吗?BEcause数据库中的所有密码都是以这种方式存储的,关键是现在只在服务器端生成相同的密码。(密码现在被加密以抵御攻击)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-09 17:42:17

使用CryptoJS/PBKDF2 2的JSFiddle (尽管我必须更正CDN链接),其相关代码是

代码语言:javascript
复制
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));

我获得了一个示例输入/输出"hello",它带有(base64)盐的0CD1HGFdkclqcWG5aV+rvw== (以及默认的哈希算法,具有指定的1000次迭代和32+32字节输出);这会产生tRczLRRuFy/zFiPn1PBKmQ== / dhyeE+0Dd9avSJbM/4TcNw==

然后使用了以下C#发现代码:

代码语言:javascript
复制
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)));
}

输出为

代码语言:javascript
复制
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==

结论: CryptoJS.PBKDF2使用的是SHA-1和UTF-8,这意味着最有可能的问题是,如果你没有得到相同的答案,你就会装入错误的盐中。如果它不是UTF-8字符串,它可能是十六进制数据或base64 (但这完全取决于您的使用,这里没有“正确的答案”,因为盐是“只是字节”)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53209486

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档