Javascript 使用WebCrypto从PBKDF2生成ECDH密钥
警告以下内容并不表示认可将密码转换为ECDH密钥。从高熵、加密安全的PRNG创建ECDH密钥 我想获取一个秘密并从中生成一个ECDH公钥/私钥 在浏览器中,通常的方法是使用PBKDF2(或其他确定性字节)在WebCrypto中生成ECDH公钥/私钥对 下面的示例代码应该可以做到这一点,但它会在Chrome中引发DOM异常:Javascript 使用WebCrypto从PBKDF2生成ECDH密钥,javascript,cryptography,diffie-hellman,Javascript,Cryptography,Diffie Hellman,警告以下内容并不表示认可将密码转换为ECDH密钥。从高熵、加密安全的PRNG创建ECDH密钥 我想获取一个秘密并从中生成一个ECDH公钥/私钥 在浏览器中,通常的方法是使用PBKDF2(或其他确定性字节)在WebCrypto中生成ECDH公钥/私钥对 下面的示例代码应该可以做到这一点,但它会在Chrome中引发DOM异常: // Generate a random KDF key. const priv = new Uint8Array(24) crypto.getRandomValues(pr
// Generate a random KDF key.
const priv = new Uint8Array(24)
crypto.getRandomValues(priv)
const kdfKey = await crypto.subtle.importKey(
'raw', priv, { name: 'PBKDF2' }, false, ['deriveKey'])
// Derive the ECDH key.
const salt = new Uint8Array(16)
const iterations = 2000
const hash = { name: 'SHA-512' }
const curve = { name: 'ECDH', namedCurve: 'P-384' }
const usages = ['deriveKey']
crypto.getRandomValues(salt)
const ecdhKey = await crypto.subtle.deriveKey({
name: 'PBKDF2', salt, iterations, hash
}, kdfKey, curve, true, usages) // throws.
当算法是AES-GCM
(即当曲线被替换为{name:'AES-GCM',length:256}
)时,上述方法有效,但其他算法也会抛出异常,因此我怀疑我遗漏了什么。。。微妙的
我希望WebCrypto适合接受随机位并生成ECDH公钥/私钥对。看起来情况可能并非如此
另一种方法是使用可用于手动创建ECDH密钥对的PBKDF2
到deriveBits
。如果这确实是唯一的选择,那么将随机位转换为公钥/私钥(即引用和公共实现)的常用算法是什么?如果我必须开发一些东西,我可能会在这里发布兴趣与评论
编辑:用例的其他详细信息
使用PBKDF是为了避免在给定(私有)d
参数时必须生成ECDH密钥对的公钥(x
和y
)。x
和y
是派生的,因此不需要存储,而且我们的数据存储非常有限-仅适用于私钥,例如192位左右(PBKDF也可以平滑位大小,但这只是一个旁白)
当给定(伪)随机d
参数时,如果WebCrypto计算x
和y
,则可获得/说明如下所示的预期结果:
>>> curve = { name: 'ECDH', namedCurve: 'P-256' }
>>> k = await crypto.subtle.generateKey(curve, true, ['deriveKey'])
>>> pri = await crypto.subtle.exportKey('jwk', k.privateKey)
>>> delete pri.x
>>> delete pri.y
>>> k2 = await crypto.subtle.importKey('jwk', pri)
^^ errors
在许多示例中,PBKDF用于生成(AES)密钥。我希望通过PBKDF2deriveKey
可以使用WebCrypto中已有的椭圆曲线计算x
和y
的功能
Javascript中自己动手的替代方法是解析JWK/Base64(URL变体),然后使用带模运算的大整数函数(例如Fermat的小定理),最后编写椭圆曲线点加法、倍增和乘法函数。这就是我所做的()。但我希望这一切都是不必要的,因为WebCrypto中有这样做的代码,我只是希望使用importKey
或deriveKey
来使用它
只是重申一下:没有用户生成的密码;使用这种方法来生成ECDH密钥被认为是不明智的。“微妙的。”很好
在阅读了上面链接中sublecrypto的密钥生成说明后,我将其放入了Chrome上的浏览器控制台,它运行良好。您可能需要对其进行调整以适应您的情况,尤其是关于关键用法的部分:
(async function() {
const algo = {
"name": "RSASSA-PKCS1-v1_5",
"modulusLength": 256,
"publicExponent": new Uint8Array([0x01, 0x00, 0x01]),
"hash": {
"name": "SHA-256"
}
};
const extractable = true;
const keyUsages = ["sign","verify"];
const result = await crypto.subtle.generateKey(algo, extractable, keyUsages);
console.log(result);
})();
布莱恩
不可能使用WebCrypto从密码确定地创建密钥对
对不起
您可以确定地从Javascript中的密码创建密钥对,然后导入该密钥对,只要它是正确表示形式的secp256r1密钥
有一些javascript库支持从密码确定地创建密钥对。我不能就这些库的正确性或安全性发表任何声明,或者是否有针对secp256r1的库这样做。当然,密钥生成是使用密码时考虑的最重要的方面之一,而基于弱的熵源这样做是不好的。p>
如果您决定继续采用这种方法,尽管导入给定类型的密钥非常简单,请参阅:
TL;DR您的里程数将随此方法而变化,但这是可能的
Ryan从更新中,我们仍然无法确定用例是什么,我们可以确定(我认为)出于某种原因,您的目标是节省存储空间。ECC密钥非常小,很难想象用例会是什么,特别是在web应用程序中,如此小的存储量需要使用较弱的方法。也就是说,前面的答案是一样的,不可能直接用webcrypto做你想做的事情。谢谢你的帖子。因此,给定一个秘密(要么
Uint8Array
要么string
),如何使用给定的函数(重新)生成ECDH
密钥对?生成随机ECDH密钥很简单,即微妙。generateKey(curve,false,['deriveKey')
其中curve
是例如{name:'ECDH','namedCurve:'P-384'}
,但不清楚如何导入、派生或确定地生成密钥对。非常感谢Ryan。我也这么怀疑,你的建议是我的应急计划。您是否有任何关于标准的参考,说明为什么PBKDF2可以用于创建AES而不是ECDH密钥?通常,您不会发现标准说明为什么某些东西通常不是一个好主意。这就是说,在密钥生成的情况下,您需要一个难以猜测的密钥,这种随机性甚至会影响到ECDH。PBDKF2是一种试图从母猪耳朵中取出一个丝绸钱包的尝试。你从密码中得到的信息熵很差,50k次的PBDKF2迭代总比没有好,但除非输入已经是一个好的密钥,否则它不会给你一个好的密钥。这里有一篇文章链接到一篇关于大脑钱包不安全性的论文-。脑钱包是源自密码短语的ECC密钥(secp256k1)。你可以阅读它来了解为什么这不是推荐的内容。还有一个链接,这里的公认答案很好地解释了你将如何进行基本概念。一旦你做到了,你就可以