Commit 7e2cd475 by cf

1.3.5

parent 11da676d
{ {
"name": "zswjs", "name": "zswjs",
"version": "1.3.4", "version": "1.3.5",
"description": "中数文API", "description": "中数文API",
"main": "dist/index.js", "main": "dist/index.js",
"scripts": { "scripts": {
......
...@@ -7,6 +7,8 @@ import { ...@@ -7,6 +7,8 @@ import {
stringToPrivateKey, stringToPrivateKey,
} from './zswjs-numeric'; } from './zswjs-numeric';
import { constructElliptic, PublicKey, Signature } from './zswjs-key-conversions'; import { constructElliptic, PublicKey, Signature } from './zswjs-key-conversions';
import { doSignature } from './smc/sm2';
import { arrayToHex, hexToUint8Array } from './zswjs-serialize';
/** Represents/stores a private key and provides easy conversion for use with `elliptic` lib */ /** Represents/stores a private key and provides easy conversion for use with `elliptic` lib */
export class PrivateKey { export class PrivateKey {
...@@ -71,7 +73,21 @@ export class PrivateKey { ...@@ -71,7 +73,21 @@ export class PrivateKey {
!(sigData[1] & 0x80) && !(sigData[1] === 0 && !(sigData[2] & 0x80)) !(sigData[1] & 0x80) && !(sigData[1] === 0 && !(sigData[2] & 0x80))
&& !(sigData[33] & 0x80) && !(sigData[33] === 0 && !(sigData[34] & 0x80)); && !(sigData[33] & 0x80) && !(sigData[33] === 0 && !(sigData[34] & 0x80));
const constructSignature = (options: EC.SignOptions): Signature => { const constructSignature = (options: EC.SignOptions): Signature => {
if(this.getType()===KeyType.gm){
const pubKeyDataHex = arrayToHex(this.getPublicKey().getData());
const hexA = doSignature(data,arrayToHex(this.key.data),{der: true, hash: false});
//console.log(hexA);
const allData= (pubKeyDataHex+hexA+"000000000000000000000000000000000000").substring(0,105*2);
return new Signature({
type: this.getType(),
data: hexToUint8Array(allData),
}, constructElliptic(this.getType()))
}
const ellipticPrivateKey = this.toElliptic(); const ellipticPrivateKey = this.toElliptic();
const ellipticSignature = ellipticPrivateKey.sign(data, options); const ellipticSignature = ellipticPrivateKey.sign(data, options);
return Signature.fromElliptic(ellipticSignature, this.getType(), this.ec, this.getPublicKey()); return Signature.fromElliptic(ellipticSignature, this.getType(), this.ec, this.getPublicKey());
}; };
......
/* eslint-disable class-methods-use-this */
import { BigInteger } from 'jsbn';
function bigintToValue(bigint: BigInteger) {
let h: any = bigint.toString(16)
if (h[0] !== '-') {
// 正数
if (h.length % 2 === 1) h = '0' + h // 补齐到整字节
else if (!h.match(/^[0-7]/)) h = '00' + h // 非0开头,则补一个全0字节
} else {
// 负数
h = h.substr(1)
let len = h.length
if (len % 2 === 1) len += 1 // 补齐到整字节
else if (!h.match(/^[0-7]/)) len += 2 // 非0开头,则补一个全0字节
let mask: any = ''
for (let i = 0; i < len; i++) mask += 'f'
mask = new BigInteger(mask, 16)
// 对绝对值取反,加1
h = mask.xor(bigint).add(BigInteger.ONE)
h = h.toString(16).replace(/^-/, '')
}
return h
}
class ASN1Object {
tlv: any;
t: string;
l: string;
v: string;
constructor() {
this.tlv = null
this.t = '00'
this.l = '00'
this.v = ''
}
/**
* 获取 der 编码比特流16进制串
*/
getEncodedHex() {
if (!this.tlv) {
this.v = this.getValue()
this.l = this.getLength()
this.tlv = this.t + this.l + this.v
}
return this.tlv
}
getLength() {
const n = this.v.length / 2 // 字节数
let nHex = n.toString(16)
if (nHex.length % 2 === 1) nHex = '0' + nHex // 补齐到整字节
if (n < 128) {
// 短格式,以 0 开头
return nHex
} else {
// 长格式,以 1 开头
const head = 128 + nHex.length / 2 // 1(1位) + 真正的长度占用字节数(7位) + 真正的长度
return head.toString(16) + nHex
}
}
getValue() {
return ''
}
}
class DERInteger extends ASN1Object {
t: string;
constructor(bigint: any) {
super()
this.t = '02' // 整型标签说明
if (bigint) this.v = bigintToValue(bigint)
}
getValue() {
return this.v
}
}
class DERSequence extends ASN1Object {
t: string;
asn1Array: any[];
constructor(asn1Array: any[]) {
super()
this.t = '30' // 序列标签说明
this.asn1Array = asn1Array
}
getValue() {
this.v = this.asn1Array.map(asn1Object => asn1Object.getEncodedHex()).join('')
return this.v
}
}
/**
* 获取 l 占用字节数
*/
function getLenOfL(str: string, start: number) {
if (+str[start + 2] < 8) return 1 // l 以0开头,则表示短格式,只占一个字节
return +str.substr(start + 2, 2) & 0x7f + 1 // 长格式,取第一个字节后7位作为长度真正占用字节数,再加上本身
}
/**
* 获取 l
*/
function getL(str: string, start: number) {
// 获取 l
const len = getLenOfL(str, start)
const l = str.substr(start + 2, len * 2)
if (!l) return -1
const bigint = +l[0] < 8 ? new BigInteger(l, 16) : new BigInteger(l.substr(2), 16)
return bigint.intValue()
}
/**
* 获取 v 的位置
*/
function getStartOfV(str: string, start: number) {
const len = getLenOfL(str, start)
return start + (len + 1) * 2
}
/**
* ASN.1 der 编码,针对 sm2 签名
*/
export function encodeDer(r: BigInteger, s: BigInteger): string {
const derR = new DERInteger(r)
const derS = new DERInteger(s)
const derSeq = new DERSequence([derR, derS])
return derSeq.getEncodedHex()
}
/**
* 解析 ASN.1 der,针对 sm2 验签
*/
export function decodeDer(input: string) {
// 结构:
// input = | tSeq | lSeq | vSeq |
// vSeq = | tR | lR | vR | tS | lS | vS |
const start = getStartOfV(input, 0)
const vIndexR = getStartOfV(input, start)
const lR = getL(input, start)
const vR = input.substr(vIndexR, lR * 2)
const nextStart = vIndexR + vR.length
const vIndexS = getStartOfV(input, nextStart)
const lS = getL(input, nextStart)
const vS = input.substr(vIndexS, lS * 2)
const r = new BigInteger(vR, 16)
const s = new BigInteger(vS, 16)
return { r, s }
}
/* eslint-disable no-case-declarations, max-len */
import { BigInteger } from 'jsbn';
/**
* 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 THREE = new BigInteger('3')
/**
* 椭圆曲线域元素
*/
class ECFieldElementFp {
constructor(public q: any, public x: any) {
this.x = x
this.q = q
// TODO if (x.compareTo(q) >= 0) error
}
/**
* 判断相等
*/
equals(other: any) {
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: any) {
return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q))
}
/**
* 相减
*/
subtract(b: any) {
return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q))
}
/**
* 相乘
*/
multiply(b: any) {
return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q))
}
/**
* 相除
*/
divide(b: any) {
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 {
public zinv : any;
constructor(public curve: any, public x: any, public y: any, public z: any) {
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: any) {
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: any) {
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: any) {
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 {
public infinity: any;
constructor(public q: any,public a: any, public b: any) {
this.q = q
this.a = this.fromBigInteger(a)
this.b = this.fromBigInteger(b)
this.infinity = new ECPointFp(this, null, null,null) // 无穷远点
}
/**
* 判断两个椭圆曲线是否相等
*/
equals(other: any) {
if (other === this) return true
return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b))
}
/**
* 生成椭圆曲线域元素
*/
fromBigInteger(x: any) {
return new ECFieldElementFp(this.q, x)
}
/**
* 解析 16 进制串为椭圆曲线点
*/
decodePointHex(s: any) {
switch (parseInt(s.substr(0, 2), 16)) {
// 第一个字节
case 0:
return this.infinity
case 2:
case 3:
// 不支持的压缩方式
return null
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)),null)
default:
// 不支持
return null
}
}
}
export {
ECPointFp,
ECCurveFp,
}
/* eslint-disable no-use-before-define */
import { BigInteger } from 'jsbn';
import { encodeDer, decodeDer } from './asn1';
import * as _ from './utils';
import sm3 from './sm3';
const {G, curve, n} = _.generateEcparam()
const C1C2C3 = 0
/**
* 加密
*/
function doEncrypt(msg: any, publicKey: any, cipherMode = 1) {
msg = typeof msg === 'string' ? _.hexToArray(_.utf8ToHex(msg)) : Array.prototype.slice.call(msg)
publicKey = _.getGlobalCurve().decodePointHex(publicKey) // 先将公钥转成点
const keypair = _.generateKeyPairHex()
const k = new BigInteger(keypair.privateKey, 16) // 随机数 k
// c1 = k * G
let c1 = keypair.publicKey
if (c1.length > 128) c1 = c1.substr(c1.length - 128)
// (x2, y2) = k * publicKey
const p = publicKey.multiply(k)
const x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64))
const y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64))
// c3 = hash(x2 || msg || y2)
const c3 = _.arrayToHex(sm3([].concat(x2, msg, y2)))
let ct = 1
let offset = 0
let t: any = [] // 256 位
const z = [].concat(x2, y2)
const nextT = () => {
// (1) Hai = hash(z || ct)
// (2) ct++
t = sm3([...z, ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff])
ct++
offset = 0
}
nextT() // 先生成 Ha1
for (let i = 0, len = msg.length; i < len; i++) {
// t = Ha1 || Ha2 || Ha3 || Ha4
if (offset === t.length) nextT()
// c2 = msg ^ t
msg[i] ^= t[offset++] & 0xff
}
const c2 = _.arrayToHex(msg)
return cipherMode === C1C2C3 ? c1 + c2 + c3 : c1 + c3 + c2
}
/**
* 解密
*/
function doDecrypt(encryptData: any, privateKey: any, cipherMode = 1, {
output = 'string',
} = {}) {
privateKey = new BigInteger(privateKey, 16)
let c3 = encryptData.substr(128, 64)
let c2 = encryptData.substr(128 + 64)
if (cipherMode === C1C2C3) {
c3 = encryptData.substr(encryptData.length - 64)
c2 = encryptData.substr(128, encryptData.length - 128 - 64)
}
const msg = _.hexToArray(c2)
const c1 = _.getGlobalCurve().decodePointHex('04' + encryptData.substr(0, 128))
const p = c1.multiply(privateKey)
const x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64))
const y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64))
let ct = 1
let offset = 0
let t: any = [] // 256 位
const z = [].concat(x2, y2)
const nextT = () => {
// (1) Hai = hash(z || ct)
// (2) ct++
t = sm3([...z, ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff])
ct++
offset = 0
}
nextT() // 先生成 Ha1
for (let i = 0, len = msg.length; i < len; i++) {
// t = Ha1 || Ha2 || Ha3 || Ha4
if (offset === t.length) nextT()
// c2 = msg ^ t
msg[i] ^= t[offset++] & 0xff
}
// c3 = hash(x2 || msg || y2)
const checkC3 = _.arrayToHex(sm3([].concat(x2, msg, y2)))
if (checkC3 === c3) {
return output === 'array' ? msg : _.arrayToUtf8(msg)
} else {
return output === 'array' ? [] : ''
}
}
/**
* 签名
*/
function doSignature(msg: any, privateKey: any, {
pointPool, der, hash, publicKey, userId
}: any = {}) {
let hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg)
if (hash) {
// sm3杂凑
publicKey = publicKey || getPublicKeyFromPrivateKey(privateKey)
hashHex = getHash(hashHex, publicKey, userId)
}
const dA = new BigInteger(privateKey, 16)
const e = new BigInteger(hashHex, 16)
// k
let k = null
let r = null
let s = null
do {
do {
let point
if (pointPool && pointPool.length) {
point = pointPool.pop()
} else {
point = getPoint()
}
k = point.k
// r = (e + x1) mod n
r = e.add(point.x1).mod(n)
} while (r.equals(BigInteger.ZERO) || r.add(k).equals(n))
// s = ((1 + dA)^-1 * (k - r * dA)) mod n
s = dA.add(BigInteger.ONE).modInverse(n).multiply(k.subtract(r.multiply(dA))).mod(n)
} while (s.equals(BigInteger.ZERO))
if (der) return encodeDer(r, s) // asn.1 der 编码
return _.leftPad(r.toString(16), 64) + _.leftPad(s.toString(16), 64)
}
/**
* 验签
*/
function doVerifySignature(msg: any, signHex: any, publicKey: any, {der, hash, userId}: any = {}) {
let hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg)
if (hash) {
// sm3杂凑
hashHex = getHash(hashHex, publicKey, userId)
}
let r; let
s
if (der) {
const decodeDerObj = decodeDer(signHex) // asn.1 der 解码
r = decodeDerObj.r
s = decodeDerObj.s
} else {
r = new BigInteger(signHex.substring(0, 64), 16)
s = new BigInteger(signHex.substring(64), 16)
}
const PA = curve.decodePointHex(publicKey)
const e = new BigInteger(hashHex, 16)
// t = (r + s) mod n
const t = r.add(s).mod(n)
if (t.equals(BigInteger.ZERO)) return false
// x1y1 = s * G + t * PA
const x1y1 = G.multiply(s).add(PA.multiply(t))
// R = (e + x1) mod n
const R = e.add(x1y1.getX().toBigInteger()).mod(n)
return r.equals(R)
}
/**
* sm3杂凑算法
*/
function getHash(hashHex: any, publicKey: any, userId = '1234567812345678') {
// z = hash(entl || userId || a || b || gx || gy || px || py)
userId = _.utf8ToHex(userId)
const a = _.leftPad(G.curve.a.toBigInteger().toRadix(16), 64)
const b = _.leftPad(G.curve.b.toBigInteger().toRadix(16), 64)
const gx = _.leftPad(G.getX().toBigInteger().toRadix(16), 64)
const gy = _.leftPad(G.getY().toBigInteger().toRadix(16), 64)
if (publicKey.length > 128) publicKey = publicKey.substr(2, 128) // 干掉 '04'
const px = publicKey.substr(0, 64)
const py = publicKey.substr(64, 64)
const data = _.hexToArray(userId + a + b + gx + gy + px + py)
const entl = userId.length * 4
data.unshift(entl & 0x00ff)
data.unshift(entl >> 8 & 0x00ff)
const z = sm3(data)
// e = hash(z || msg)
return _.arrayToHex(sm3(z.concat(_.hexToArray(hashHex))))
}
/**
* 计算公钥
*/
function getPublicKeyFromPrivateKey(privateKey: any) {
const PA = G.multiply(new BigInteger(privateKey, 16))
const x = _.leftPad(PA.getX().toBigInteger().toString(16), 64)
const y = _.leftPad(PA.getY().toBigInteger().toString(16), 64)
return '04' + x + y
}
/**
* 获取椭圆曲线点
*/
function getPoint() {
const keypair:any = _.generateKeyPairHex()
const PA = curve.decodePointHex(keypair.publicKey)
keypair.k = new BigInteger(keypair.privateKey, 16)
keypair.x1 = PA.getX().toBigInteger()
return keypair
}
const generateKeyPairHex = _.generateKeyPairHex;
const verifyPublicKey = _.verifyPublicKey;
export {
generateKeyPairHex,
doEncrypt,
doDecrypt,
doSignature,
doVerifySignature,
getPoint,
verifyPublicKey,
}
/**
* 循环左移
*/
function rotl(x: any, n: any) {
const result = []
const a = ~~(n / 8) // 偏移 a 字节
const b = n % 8 // 偏移 b 位
for (let i = 0, len = x.length; i < len; i++) {
// current << b + (current + 1) >>> (8 - b)
result[i] = ((x[(i + a) % len] << b) & 0xff) + ((x[(i + a + 1) % len] >>> (8 - b)) & 0xff)
}
return result
}
/**
* 二进制异或运算
*/
function xor(x: any, y: any) {
const result = []
for (let i = x.length - 1; i >= 0; i--) result[i] = (x[i] ^ y[i]) & 0xff
return result
}
/**
* 二进制与运算
*/
function and(x: any, y: any) {
const result = []
for (let i = x.length - 1; i >= 0; i--) result[i] = (x[i] & y[i]) & 0xff
return result
}
/**
* 二进制或运算
*/
function or(x: any, y: any) {
const result = []
for (let i = x.length - 1; i >= 0; i--) result[i] = (x[i] | y[i]) & 0xff
return result
}
/**
* 二进制与运算
*/
function add(x: any, y: any) {
const result = []
let temp = 0
for (let i = x.length - 1; i >= 0; i--) {
const sum = x[i] + y[i] + temp
if (sum > 0xff) {
temp = 1
result[i] = sum & 0xff
} else {
temp = 0
result[i] = sum & 0xff
}
}
return result
}
/**
* 二进制非运算
*/
function not(x: any) {
const result = []
for (let i = x.length - 1; i >= 0; i--) result[i] = (~x[i]) & 0xff
return result
}
/**
* 压缩函数中的置换函数 P1(X) = X xor (X <<< 9) xor (X <<< 17)
*/
function P0(X: any) {
return xor(xor(X, rotl(X, 9)), rotl(X, 17))
}
/**
* 消息扩展中的置换函数 P1(X) = X xor (X <<< 15) xor (X <<< 23)
*/
function P1(X: any) {
return xor(xor(X, rotl(X, 15)), rotl(X, 23))
}
/**
* 布尔函数 FF
*/
function FF(X: any, Y: any, Z: any, j: any) {
return j >= 0 && j <= 15 ? xor(xor(X, Y), Z) : or(or(and(X, Y), and(X, Z)), and(Y, Z))
}
/**
* 布尔函数 GG
*/
function GG(X: any, Y: any, Z: any, j: any) {
return j >= 0 && j <= 15 ? xor(xor(X, Y), Z) : or(and(X, Y), and(not(X), Z))
}
/**
* 压缩函数
*/
function CF(V: any, Bi: any) {
// 消息扩展
const W = []
const M = [] // W'
// 将消息分组B划分为 16 个字 W0, W1,……,W15
for (let i = 0; i < 16; i++) {
const start = i * 4
W.push(Bi.slice(start, start + 4))
}
// W16 ~ W67:W[j] <- P1(W[j−16] xor W[j−9] xor (W[j−3] <<< 15)) xor (W[j−13] <<< 7) xor W[j−6]
for (let j = 16; j < 68; j++) {
W.push(xor(
xor(
P1(
xor(
xor(W[j - 16], W[j - 9]),
rotl(W[j - 3], 15)
)
),
rotl(W[j - 13], 7)
),
W[j - 6]
))
}
// W′0 ~ W′63:W′[j] = W[j] xor W[j+4]
for (let j = 0; j < 64; j++) {
M.push(xor(W[j], W[j + 4]))
}
// 压缩
const T1 = [0x79, 0xcc, 0x45, 0x19]
const T2 = [0x7a, 0x87, 0x9d, 0x8a]
// 字寄存器
let A = V.slice(0, 4)
let B = V.slice(4, 8)
let C = V.slice(8, 12)
let D = V.slice(12, 16)
let E = V.slice(16, 20)
let F = V.slice(20, 24)
let G = V.slice(24, 28)
let H = V.slice(28, 32)
// 中间变量
let SS1
let SS2
let TT1
let TT2
for (let j = 0; j < 64; j++) {
const T = j >= 0 && j <= 15 ? T1 : T2
SS1 = rotl(add(
add(rotl(A, 12), E),
rotl(T, j)
), 7)
SS2 = xor(SS1, rotl(A, 12))
TT1 = add(add(add(FF(A, B, C, j), D), SS2), M[j])
TT2 = add(add(add(GG(E, F, G, j), H), SS1), W[j])
D = C
C = rotl(B, 9)
B = A
A = TT1
H = G
G = rotl(F, 19)
F = E
E = P0(TT2)
}
return xor([].concat(A, B, C, D, E, F, G, H), V)
}
function main(array: any) {
// 填充
let len : any= array.length * 8
// k 是满足 len + 1 + k = 448mod512 的最小的非负整数
let k = len % 512
// 如果 448 <= (512 % len) < 512,需要多补充 (len % 448) 比特'0'以满足总比特长度为512的倍数
k = k >= 448 ? 512 - (k % 448) - 1 : 448 - k - 1
// 填充
const kArr = new Array((k - 7) / 8)
for (let i = 0, len = kArr.length; i < len; i++) kArr[i] = 0
const lenArr = []
len = len.toString(2)
for (let i = 7; i >= 0; i--) {
if (len.length > 8) {
const start = len.length - 8
lenArr[i] = parseInt(len.substr(start), 2)
len = len.substr(0, start)
} else if (len.length > 0) {
lenArr[i] = parseInt(len, 2)
len = ''
} else {
lenArr[i] = 0
}
}
const m = [].concat(array, [0x80], kArr, lenArr)
// 迭代压缩
const n = m.length / 64
let V = [0x73, 0x80, 0x16, 0x6f, 0x49, 0x14, 0xb2, 0xb9, 0x17, 0x24, 0x42, 0xd7, 0xda, 0x8a, 0x06, 0x00, 0xa9, 0x6f, 0x30, 0xbc, 0x16, 0x31, 0x38, 0xaa, 0xe3, 0x8d, 0xee, 0x4d, 0xb0, 0xfb, 0x0e, 0x4e]
for (let i = 0; i < n; i++) {
const start = 64 * i
const B = m.slice(start, start + 64)
V = CF(V, B)
}
return V
}
export default main;
\ No newline at end of file
/* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */
//@ts-ignore
import {BigInteger, SecureRandom} from 'jsbn';
import { ECCurveFp } from './ec';
const rng = new SecureRandom()
const {curve, G, n} = generateEcparam()
/**
* 获取公共椭圆曲线
*/
function getGlobalCurve() {
return curve
}
/**
* 生成ecparam
*/
function generateEcparam() {
// 椭圆曲线
const p = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16)
const a = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16)
const b = new BigInteger('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16)
const curve = new ECCurveFp(p, a, b)
// 基点
const gxHex = '32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7'
const gyHex = 'BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0'
const G = curve.decodePointHex('04' + gxHex + gyHex)
const n = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16)
return {curve, G, n}
}
/**
* 生成密钥对:publicKey = privateKey * G
*/
function generateKeyPairHex(a?: any, b?: any, c?: any) {
const random = a ? new BigInteger(a, b, c) : new BigInteger(n.bitLength(), rng)
const d = random.mod(n.subtract(BigInteger.ONE)).add(BigInteger.ONE) // 随机数
const privateKey = leftPad(d.toString(16), 64)
const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥
const Px = leftPad(P.getX().toBigInteger().toString(16), 64)
const Py = leftPad(P.getY().toBigInteger().toString(16), 64)
const publicKey = '04' + Px + Py
return {privateKey, publicKey}
}
/**
* utf8串转16进制串
*/
function utf8ToHex(input: any) {
input = unescape(encodeURIComponent(input))
const length = input.length
// 转换到字数组
const words:any = []
for (let i = 0; i < length; i++) {
words[i >>> 2] |= (input.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8)
}
// 转换到16进制
const hexChars = []
for (let i = 0; i < length; i++) {
const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
hexChars.push((bite >>> 4).toString(16))
hexChars.push((bite & 0x0f).toString(16))
}
return hexChars.join('')
}
/**
* 补全16进制字符串
*/
function leftPad(input: any, num: any) {
if (input.length >= num) return input
return (new Array(num - input.length + 1)).join('0') + input
}
/**
* 转成16进制串
*/
function arrayToHex(arr: any) {
return arr.map((item: any) => {
item = item.toString(16)
return item.length === 1 ? '0' + item : item
}).join('')
}
/**
* 转成utf8串
*/
function arrayToUtf8(arr: any) {
const words: any = []
let j = 0
for (let i = 0; i < arr.length * 2; i += 2) {
words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4)
j++
}
try {
const latin1Chars = []
for (let i = 0; i < arr.length; i++) {
const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
latin1Chars.push(String.fromCharCode(bite))
}
return decodeURIComponent(escape(latin1Chars.join('')))
} catch (e) {
throw new Error('Malformed UTF-8 data')
}
}
/**
* 转成字节数组
*/
function hexToArray(hexStr: any) {
const words = []
let hexStrLength = hexStr.length
if (hexStrLength % 2 !== 0) {
hexStr = leftPad(hexStr, hexStrLength + 1)
}
hexStrLength = hexStr.length
for (let i = 0; i < hexStrLength; i += 2) {
words.push(parseInt(hexStr.substr(i, 2), 16))
}
return words
}
/**
* 验证公钥是否为椭圆曲线上的点
*/
function verifyPublicKey(publicKey: any) {
const point = curve.decodePointHex(publicKey)
if (!point) return false
const x = point.getX()
const y = point.getY()
// 验证 y^2 是否等于 x^3 + ax + b
return y.square().equals(x.multiply(x.square()).add(x.multiply(curve.a)).add(curve.b))
}
export {
getGlobalCurve,
generateEcparam,
generateKeyPairHex,
utf8ToHex,
leftPad,
arrayToHex,
arrayToUtf8,
hexToArray,
verifyPublicKey,
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment