@dioxide-js/silas
Version:
RPC utility for Silas
347 lines (297 loc) • 9.2 kB
JavaScript
import { __require as requireJsbn } from '../../../jsbn/index.mjs';
/* eslint-disable no-case-declarations, max-len */
var ec;
var hasRequiredEc;
function requireEc () {
if (hasRequiredEc) return ec;
hasRequiredEc = 1;
const {BigInteger} = requireJsbn();
/**
* thanks for Tom Wu : http://www-cs-students.stanford.edu/~tjw/jsbn/
*
* Basic Javascript Elliptic Curve implementation
* Ported loosely from BouncyCastle's Java EC code
* Only Fp curves implemented for now
*/
const TWO = new BigInteger('2');
const THREE = new BigInteger('3');
/**
* 椭圆曲线域元素
*/
class ECFieldElementFp {
constructor(q, x) {
this.x = x;
this.q = q;
// TODO if (x.compareTo(q) >= 0) error
}
/**
* 判断相等
*/
equals(other) {
if (other === this) return true
return (this.q.equals(other.q) && this.x.equals(other.x))
}
/**
* 返回具体数值
*/
toBigInteger() {
return this.x
}
/**
* 取反
*/
negate() {
return new ECFieldElementFp(this.q, this.x.negate().mod(this.q))
}
/**
* 相加
*/
add(b) {
return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q))
}
/**
* 相减
*/
subtract(b) {
return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q))
}
/**
* 相乘
*/
multiply(b) {
return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q))
}
/**
* 相除
*/
divide(b) {
return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q))
}
/**
* 平方
*/
square() {
return new ECFieldElementFp(this.q, this.x.square().mod(this.q))
}
}
class ECPointFp {
constructor(curve, x, y, z) {
this.curve = curve;
this.x = x;
this.y = y;
// 标准射影坐标系:zinv == null 或 z * zinv == 1
this.z = z == null ? BigInteger.ONE : z;
this.zinv = null;
// TODO: compression flag
}
getX() {
if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q);
return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q))
}
getY() {
if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q);
return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q))
}
/**
* 判断相等
*/
equals(other) {
if (other === this) return true
if (this.isInfinity()) return other.isInfinity()
if (other.isInfinity()) return this.isInfinity()
// u = y2 * z1 - y1 * z2
const u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q);
if (!u.equals(BigInteger.ZERO)) return false
// v = x2 * z1 - x1 * z2
const v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q);
return v.equals(BigInteger.ZERO)
}
/**
* 是否是无穷远点
*/
isInfinity() {
if ((this.x === null) && (this.y === null)) return true
return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO)
}
/**
* 取反,x 轴对称点
*/
negate() {
return new ECPointFp(this.curve, this.x, this.y.negate(), this.z)
}
/**
* 相加
*
* 标准射影坐标系:
*
* λ1 = x1 * z2
* λ2 = x2 * z1
* λ3 = λ1 − λ2
* λ4 = y1 * z2
* λ5 = y2 * z1
* λ6 = λ4 − λ5
* λ7 = λ1 + λ2
* λ8 = z1 * z2
* λ9 = λ3^2
* λ10 = λ3 * λ9
* λ11 = λ8 * λ6^2 − λ7 * λ9
* x3 = λ3 * λ11
* y3 = λ6 * (λ9 * λ1 − λ11) − λ4 * λ10
* z3 = λ10 * λ8
*/
add(b) {
if (this.isInfinity()) return b
if (b.isInfinity()) return this
const x1 = this.x.toBigInteger();
const y1 = this.y.toBigInteger();
const z1 = this.z;
const x2 = b.x.toBigInteger();
const y2 = b.y.toBigInteger();
const z2 = b.z;
const q = this.curve.q;
const w1 = x1.multiply(z2).mod(q);
const w2 = x2.multiply(z1).mod(q);
const w3 = w1.subtract(w2);
const w4 = y1.multiply(z2).mod(q);
const w5 = y2.multiply(z1).mod(q);
const w6 = w4.subtract(w5);
if (BigInteger.ZERO.equals(w3)) {
if (BigInteger.ZERO.equals(w6)) {
return this.twice() // this == b,计算自加
}
return this.curve.infinity // this == -b,则返回无穷远点
}
const w7 = w1.add(w2);
const w8 = z1.multiply(z2).mod(q);
const w9 = w3.square().mod(q);
const w10 = w3.multiply(w9).mod(q);
const w11 = w8.multiply(w6.square()).subtract(w7.multiply(w9)).mod(q);
const x3 = w3.multiply(w11).mod(q);
const y3 = w6.multiply(w9.multiply(w1).subtract(w11)).subtract(w4.multiply(w10)).mod(q);
const z3 = w10.multiply(w8).mod(q);
return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3)
}
/**
* 自加
*
* 标准射影坐标系:
*
* λ1 = 3 * x1^2 + a * z1^2
* λ2 = 2 * y1 * z1
* λ3 = y1^2
* λ4 = λ3 * x1 * z1
* λ5 = λ2^2
* λ6 = λ1^2 − 8 * λ4
* x3 = λ2 * λ6
* y3 = λ1 * (4 * λ4 − λ6) − 2 * λ5 * λ3
* z3 = λ2 * λ5
*/
twice() {
if (this.isInfinity()) return this
if (!this.y.toBigInteger().signum()) return this.curve.infinity
const x1 = this.x.toBigInteger();
const y1 = this.y.toBigInteger();
const z1 = this.z;
const q = this.curve.q;
const a = this.curve.a.toBigInteger();
const w1 = x1.square().multiply(THREE).add(a.multiply(z1.square())).mod(q);
const w2 = y1.shiftLeft(1).multiply(z1).mod(q);
const w3 = y1.square().mod(q);
const w4 = w3.multiply(x1).multiply(z1).mod(q);
const w5 = w2.square().mod(q);
const w6 = w1.square().subtract(w4.shiftLeft(3)).mod(q);
const x3 = w2.multiply(w6).mod(q);
const y3 = w1.multiply(w4.shiftLeft(2).subtract(w6)).subtract(w5.shiftLeft(1).multiply(w3)).mod(q);
const z3 = w2.multiply(w5).mod(q);
return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3)
}
/**
* 倍点计算
*/
multiply(k) {
if (this.isInfinity()) return this
if (!k.signum()) return this.curve.infinity
// 使用加减法
const k3 = k.multiply(THREE);
const neg = this.negate();
let Q = this;
for (let i = k3.bitLength() - 2; i > 0; i--) {
Q = Q.twice();
const k3Bit = k3.testBit(i);
const kBit = k.testBit(i);
if (k3Bit !== kBit) {
Q = Q.add(k3Bit ? this : neg);
}
}
return Q
}
}
/**
* 椭圆曲线 y^2 = x^3 + ax + b
*/
class ECCurveFp {
constructor(q, a, b) {
this.q = q;
this.a = this.fromBigInteger(a);
this.b = this.fromBigInteger(b);
this.infinity = new ECPointFp(this, null, null); // 无穷远点
}
/**
* 判断两个椭圆曲线是否相等
*/
equals(other) {
if (other === this) return true
return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b))
}
/**
* 生成椭圆曲线域元素
*/
fromBigInteger(x) {
return new ECFieldElementFp(this.q, x)
}
/**
* 解析 16 进制串为椭圆曲线点
*/
decodePointHex(s) {
switch (parseInt(s.substr(0, 2), 16)) {
// 第一个字节
case 0:
return this.infinity
case 2:
case 3:
// 压缩
const x = this.fromBigInteger(new BigInteger(s.substr(2), 16));
// 对 p ≡ 3 (mod4),即存在正整数 u,使得 p = 4u + 3
// 计算 y = (√ (x^3 + ax + b) % p)^(u + 1) modp
let y = this.fromBigInteger(x.multiply(x.square()).add(
x.multiply(this.a)
).add(this.b).toBigInteger()
.modPow(
this.q.divide(new BigInteger('4')).add(BigInteger.ONE), this.q
));
// 算出结果 2 进制最后 1 位不等于第 1 个字节减 2 则取反
if (!y.toBigInteger().mod(TWO).equals(new BigInteger(s.substr(0, 2), 16).subtract(TWO))) {
y = y.negate();
}
return new ECPointFp(this, x, y)
case 4:
case 6:
case 7:
const len = (s.length - 2) / 2;
const xHex = s.substr(2, len);
const yHex = s.substr(len + 2, len);
return new ECPointFp(this, this.fromBigInteger(new BigInteger(xHex, 16)), this.fromBigInteger(new BigInteger(yHex, 16)))
default:
// 不支持
return null
}
}
}
ec = {
ECPointFp,
ECCurveFp,
};
return ec;
}
export { requireEc as __require };
//# sourceMappingURL=ec.mjs.map