javascript - 椭圆曲线点压缩算法

标签 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

这些素数都满足方程p mod 4 === 3
这意味着您可以跳过有点复杂的通用目的 Tonelli-Shanks algorithm , 并使用简单恒等式求平方根。

首先,'点压缩'的压缩部分非常简单。记录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;
}

解压缩涉及查找平方根,然后根据 Y 奇偶校验位进行校正。 此功能取决于 JavaScript big integer library它公开了以下函数: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()
    };
}

关于javascript - 椭圆曲线点压缩算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17171542/

相关文章:

cryptography - 需要有关双线性 map 的信息

elliptic-curve - 通过具有 ec 公钥坐标构建 PEM 文件

java - 如何使用椭圆曲线私钥和 ECDSA 算法对证书进行签名?

javascript - Episerver中通过AJAX请求更新后刷新页面

javascript - $scope 上定义的变量直到下一个周期才会更新

javascript - 使用socket.io和node.js时更改文件目录?

c - 如何在C中使用RSA加密多个文件

javascript - sha3输出可以用作文件名吗?

security - 为什么P-521公钥X,Y有时是65字节有时是66字节

javascript - 更新 : USER ERROR - TYPO ! ! grunt-contrib-coffee 查找文件和写入目标时出错