Ian*_*ton 8 javascript cryptography elliptic-curve
我正在使用Javascript生成椭圆曲线,以便在基于此示例代码的加密消息传递应用程序中使用http://www-cs-students.stanford.edu/~tjw/jsbn/ecdh.html
公钥将非常大,我知道可以压缩它们,但我一直无法找到Javascript或大纲算法来执行此操作.这是一篇文章http://nmav.gnutls.org/2012/01/do-we-need-elliptic-curve-point.html,概述了数学.
我想他们会对JavaScript椭圆曲线点压缩解决方案产生兴趣,WebCrypto支持过滤到浏览器中.
我将使用NIST曲线作为示例,因为这些是我在将压缩的公钥导入WebCrypto时必须处理的.
Curves and their primes
NIST P-256 (secp256r1) 2^256 - 2^224 + 2^192 + 2^96 - 1
NIST P-384 (secp384r1) 2^384 - 2^128 - 2^96 + 2^32 - 1
NIST P-521 (secp521r1) 2^521 - 1
Run Code Online (Sandbox Code Playgroud)
这些素数都满足等式,p mod 4 === 3
这意味着你可以跳过有些复杂的通用Tonelli-Shanks算法,并使用简单的身份来找到平方根.
首先,"点压缩"的压缩部分非常简单.记录Y的符号,然后丢弃Y的值.
/**
* Point compress elliptic curve key
* @param {Uint8Array} x component
* @param {Uint8Array} y component
* @return {Uint8Array} Compressed representation
*/
function ECPointCompress( x, y )
{
const out = new Uint8Array( x.length + 1 );
out[0] = 2 + ( y[ y.length-1 ] & 1 );
out.set( x, 1 );
return out;
}
Run Code Online (Sandbox Code Playgroud)
解压缩包括查找平方根,然后根据Y奇偶校验位进行校正.此函数依赖于一个JavaScript大整数库,它暴露了以下函数:add,sub,multiply,pow,modPow.
// Consts for P256 curve. Adjust accordingly
const two = new bigInt(2),
// 115792089210356248762697446949407573530086143415290314195533631308867097853951
prime = two.pow(256).sub( two.pow(224) ).add( two.pow(192) ).add( two.pow(96) ).sub(1),
b = new bigInt( '41058363725152142129326129780047268409114441015993725554835256314039467401291' ),
// Pre-computed value, or literal
pIdent = prime.add(1).divide(4); // 28948022302589062190674361737351893382521535853822578548883407827216774463488
/**
* Point decompress NIST curve
* @param {Uint8Array} Compressed representation
* @return {Object} Explicit x & y
*/
function ECPointDecompress( comp )
{
const signY = comp[0] - 2, // This value must be 2 or 3. 4 indicates an uncompressed key, and anything else is invalid.
x = comp.subarray(1),
// Import x into bigInt library
xBig = new bigInt( x );
// y^2 = x^3 - 3x + b
var yBig = xBig.pow(3).sub( xBig.multiply(3) ).add( b ).modPow( pIdent, prime );
// If the parity doesn't match it's the *other* root
if( yBig.mod(2) !== signY )
{
// y = prime - y
yBig = prime.sub( yBig );
}
return {
x: x,
y: yBig.toUint8Array()
};
}
Run Code Online (Sandbox Code Playgroud)