Commit a6d35a62 a6d35a62b5bd55f0f6501bbe737c6b6d3c68a14b by wulianyou

first commit

0 parents
{
"presets": ["es2015"]
}
\ No newline at end of file
module.exports = {
'extends': [
'airbnb-base',
'plugin:promise/recommended'
],
'parserOptions': {
'ecmaVersion': 9,
'ecmaFeatures': {
'jsx': false
},
'sourceType': 'module'
},
'env': {
'es6': true,
'node': true,
'jest': true
},
'plugins': [
'import',
'node',
'promise'
],
'rules': {
'arrow-parens': 'off',
'comma-dangle': [
'error',
'only-multiline'
],
'complexity': ['error', 10],
'func-names': 'off',
'global-require': 'off',
'handle-callback-err': [
'error',
'^(err|error)$'
],
'import/no-unresolved': [
'error',
{
'caseSensitive': true,
'commonjs': true,
'ignore': ['^[^.]']
}
],
'import/prefer-default-export': 'off',
'linebreak-style': 'off',
'no-catch-shadow': 'error',
'no-continue': 'off',
'no-div-regex': 'warn',
'no-else-return': 'off',
'no-param-reassign': 'off',
'no-plusplus': 'off',
'no-shadow': 'off',
'no-multi-assign': 'off',
'no-underscore-dangle': 'off',
'node/no-deprecated-api': 'error',
'node/process-exit-as-throw': 'error',
'object-curly-spacing': [
'error',
'never'
],
'operator-linebreak': [
'error',
'after',
{
'overrides': {
':': 'before',
'?': 'before'
}
}
],
'prefer-arrow-callback': 'off',
'prefer-destructuring': 'off',
'prefer-template': 'off',
'quote-props': [
1,
'as-needed',
{
'unnecessary': true
}
],
'semi': [
'error',
'never'
],
'max-len': 'off',
},
'globals': {
'window': true,
'document': true,
'App': true,
'Page': true,
'Component': true,
'Behavior': true
}
}
.DS_Store
.idea
node_modules
npm-debug.log
package-lock.json
\ No newline at end of file
{
"name": "@ddn/sm-crypto",
"version": "0.0.1",
"description": "@ddn/sm-crypto,基于sm-crypto。",
"main": "src/index.js",
"scripts": {
"prepublish": "npm run build",
"test": "jest ./test/*",
"lint": "eslint \"src/**/*.js\" --fix",
"build": "npm run lint && webpack"
},
"repository": {
"type": "git",
"url": "git+https://github.com/ddnlink"
},
"keywords": [
"ddn",
"sm",
"js",
"crypto"
],
"jest": {
"testEnvironment": "jsdom",
"testURL": "https://jest.test"
},
"author": "creazy",
"license": "MIT",
"dependencies": {
"jsbn": "^1.1.0"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.24.1",
"jest": "^22.1.4",
"webpack": "^3.10.0",
"eslint": "^5.3.0",
"eslint-config-airbnb-base": "13.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-node": "^7.0.1",
"eslint-plugin-promise": "^3.8.0"
}
}
{
"name": "@ddn/sm-crypto",
"version": "0.0.1",
"description": "@ddn/sm-crypto,基于sm-crypto。",
"main": "src/index.js",
"scripts": {
"prepublish": "npm run build",
"test": "jest ./test/*",
"lint": "eslint \"src/**/*.js\" --fix",
"build": "npm run lint && webpack"
},
"repository": {
"type": "git",
"url": "git+https://github.com/ddnlink"
},
"files": [
"dist",
"README.md"
],
"keywords": [
"ddn",
"sm",
"js",
"crypto"
],
"jest": {
"testEnvironment": "jsdom",
"testURL": "https://jest.test"
},
"author": "creazy",
"license": "MIT",
"dependencies": {
"jsbn": "^1.1.0"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.24.1",
"jest": "^22.1.4",
"webpack": "^3.10.0",
"eslint": "^5.3.0",
"eslint-config-airbnb-base": "13.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-node": "^7.0.1",
"eslint-plugin-promise": "^3.8.0"
}
}
{
"name": "@ddn/sm-crypto",
"version": "0.0.1",
"description": "@ddn/sm-crypto,基于sm-crypto。",
"main": "dist/index.js",
"scripts": {
"prepublish": "npm run build",
"test": "jest ./test/*",
"lint": "eslint \"src/**/*.js\" --fix",
"build": "npm run lint && webpack"
},
"repository": {
"type": "git",
"url": "git+https://github.com/ddnlink"
},
"files": [
"dist",
"README.md"
],
"keywords": [
"ddn",
"sm",
"js",
"crypto"
],
"jest": {
"testEnvironment": "jsdom",
"testURL": "https://jest.test"
},
"author": "creazy",
"license": "MIT",
"dependencies": {
"jsbn": "^1.1.0"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.24.1",
"jest": "^22.1.4",
"webpack": "^3.10.0",
"eslint": "^5.3.0",
"eslint-config-airbnb-base": "13.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-node": "^7.0.1",
"eslint-plugin-promise": "^3.8.0"
}
}
/* eslint-disable no-case-declarations, max-len */
const {BigInteger} = require('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(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:
// 不支持的压缩方式
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)))
default:
// 不支持
return null
}
}
}
module.exports = {
ECPointFp,
ECCurveFp,
}
/* eslint-disable no-case-declarations, max-len */
const {BigInteger} = require('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(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:
// 不支持的压缩方式
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)))
default:
// 不支持
return null
}
}
}
module.exports = {
ECPointFp,
ECCurveFp,
}
/* eslint-disable no-case-declarations, max-len */
const {BigInteger} = require('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(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:
// 不支持的压缩方式
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)))
default:
// 不支持
return null
}
}
}
module.exports = {
ECPointFp,
ECCurveFp,
}
/* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */
const {BigInteger, SecureRandom} = require('jsbn')
const {ECCurveFp} = require('./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}
}
/**
* 生成密钥对
*/
function generateKeyPairHex() {
const d = new BigInteger(n.bitLength(), rng).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}
}
/**
* 根据指定hash值,生成密钥对
* @param {String} hashValue
*/
function generateKeyPairHexByHashValue(hashValue) {
const d = new BigInteger(hashValue, 16)
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 = '0x' + Px + Py
return {privateKey, publicKey}
}
/**
* 解析utf8字符串到16进制
*/
function parseUtf8StringToHex(input) {
input = unescape(encodeURIComponent(input))
const length = input.length
// 转换到字数组
const words = []
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('')
}
/**
* 解析arrayBuffer到16进制字符串
*/
function parseArrayBufferToHex(input) {
return Array.prototype.map.call(new Uint8Array(input), x => ('00' + x.toString(16)).slice(-2)).join('')
}
/**
* 补全16进制字符串
*/
function leftPad(input, num) {
if (input.length >= num) return input
return (new Array(num - input.length + 1)).join('0') + input
}
/**
* 转成16进制串
*/
function arrayToHex(arr) {
const words = []
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++
}
// 转换到16进制
const hexChars = []
for (let i = 0; i < arr.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('')
}
/**
* 转成utf8串
*/
function arrayToUtf8(arr) {
const words = []
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')
}
}
/**
* 转成ascii码数组
*/
function hexToArray(hexStr) {
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
}
module.exports = {
getGlobalCurve,
generateEcparam,
generateKeyPairHex,
generateKeyPairHexByHashValue,
parseUtf8StringToHex,
parseArrayBufferToHex,
leftPad,
arrayToHex,
arrayToUtf8,
hexToArray,
}
/* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */
const {BigInteger, SecureRandom} = require('jsbn')
const {ECCurveFp} = require('./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}
}
/**
* 生成密钥对
*/
function generateKeyPairHex() {
const d = new BigInteger(n.bitLength(), rng).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}
}
/**
* 根据指定hash值,生成密钥对
* @param {String} hashValue
*/
function generateKeyPairHexByHashValue(hashValue) {
const d = new BigInteger(hashValue, 16)
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 parseUtf8StringToHex(input) {
input = unescape(encodeURIComponent(input))
const length = input.length
// 转换到字数组
const words = []
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('')
}
/**
* 解析arrayBuffer到16进制字符串
*/
function parseArrayBufferToHex(input) {
return Array.prototype.map.call(new Uint8Array(input), x => ('00' + x.toString(16)).slice(-2)).join('')
}
/**
* 补全16进制字符串
*/
function leftPad(input, num) {
if (input.length >= num) return input
return (new Array(num - input.length + 1)).join('0') + input
}
/**
* 转成16进制串
*/
function arrayToHex(arr) {
const words = []
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++
}
// 转换到16进制
const hexChars = []
for (let i = 0; i < arr.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('')
}
/**
* 转成utf8串
*/
function arrayToUtf8(arr) {
const words = []
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')
}
}
/**
* 转成ascii码数组
*/
function hexToArray(hexStr) {
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
}
module.exports = {
getGlobalCurve,
generateEcparam,
generateKeyPairHex,
generateKeyPairHexByHashValue,
parseUtf8StringToHex,
parseArrayBufferToHex,
leftPad,
arrayToHex,
arrayToUtf8,
hexToArray,
}
/* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */
const {BigInteger, SecureRandom} = require('jsbn')
const {ECCurveFp} = require('./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}
}
/**
* 生成密钥对
*/
function generateKeyPairHex() {
const d = new BigInteger(n.bitLength(), rng).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}
}
/**
* 根据指定hash值,生成密钥对
* @param {String} hashValue
*/
function generateKeyPairHexByHashValue(hashValue) {
const d = new BigInteger(hashValue, 16)
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 parseUtf8StringToHex(input) {
input = unescape(encodeURIComponent(input))
const length = input.length
// 转换到字数组
const words = []
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('')
}
/**
* 解析arrayBuffer到16进制字符串
*/
function parseArrayBufferToHex(input) {
return Array.prototype.map.call(new Uint8Array(input), x => ('00' + x.toString(16)).slice(-2)).join('')
}
/**
* 补全16进制字符串
*/
function leftPad(input, num) {
if (input.length >= num) return input
return (new Array(num - input.length + 1)).join('0') + input
}
/**
* 转成16进制串
*/
function arrayToHex(arr) {
const words = []
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++
}
// 转换到16进制
const hexChars = []
for (let i = 0; i < arr.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('')
}
/**
* 转成utf8串
*/
function arrayToUtf8(arr) {
const words = []
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')
}
}
/**
* 转成ascii码数组
*/
function hexToArray(hexStr) {
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
}
module.exports = {
getGlobalCurve,
generateEcparam,
generateKeyPairHex,
generateKeyPairHexByHashValue,
parseUtf8StringToHex,
parseArrayBufferToHex,
leftPad,
arrayToHex,
arrayToUtf8,
hexToArray,
}
const sm2 = require('sm-crypto').sm2
function getKeys(secret) {
// const hash = createHash(Buffer.from(secret))
// const m = new Uint8Array(nacl.sign.seedLength)
// for (let i = 0; i < m.length; i++) m[i] = hash[i]
// const keypair = nacl.sign.keyPair.fromSeed(m)
/**
* {
publicKey: '0x10d15cb4a3747d9bcf6339ef7b1d8462e86da595e7da3f4dd17bb1b7e3b43cf9c67e41a439ec1ddae15e697b71bbfa2c4f662fce5105fc21c404df9ddae513f7',
privateKey: '5c3e9a13ff5618cca46bdf5780c4391e89af27eeea044c90ad9684f4fb51c453'
}
*/
const keypair =sm2.generateKeyPairHex(secret)
let sigValueHex = sm2.doSignature(secret, keypair.privateKey)
let verifyResult = sm2.doVerifySignature(secret, sigValueHex, keypair.publicKey)
console.log(verifyResult)
return {
publicKey: (keypair.publicKey),
privateKey: (keypair.privateKey)
}
}
function bufToHex(data) {
return Buffer.from(data).toString('hex')
}
console.log(getKeys("enter boring shaft rent essence foil trick vibrant fabric quote indoor output"))
const sm2 = require('sm-crypto').sm2
function getKeys(secret) {
// const hash = createHash(Buffer.from(secret))
// const m = new Uint8Array(nacl.sign.seedLength)
// for (let i = 0; i < m.length; i++) m[i] = hash[i]
// const keypair = nacl.sign.keyPair.fromSeed(m)
/**
* {
publicKey: '0x10d15cb4a3747d9bcf6339ef7b1d8462e86da595e7da3f4dd17bb1b7e3b43cf9c67e41a439ec1ddae15e697b71bbfa2c4f662fce5105fc21c404df9ddae513f7',
privateKey: '5c3e9a13ff5618cca46bdf5780c4391e89af27eeea044c90ad9684f4fb51c453'
}
*/
const keypair =sm2.generateKeyPairHex(secret)
// let sigValueHex = sm2.doSignature(secret, keypair.privateKey)
// let verifyResult = sm2.doVerifySignature(secret, sigValueHex, keypair.publicKey)
// console.log(verifyResult)
return {
publicKey: (keypair.publicKey),
privateKey: (keypair.privateKey)
}
}
function bufToHex(data) {
return Buffer.from(data).toString('hex')
}
console.log(getKeys("enter boring shaft rent essence foil trick vibrant fabric quote indoor output"))
const sm2 = require('sm-crypto').sm2
function getKeys(secret) {
// const hash = createHash(Buffer.from(secret))
// const m = new Uint8Array(nacl.sign.seedLength)
// for (let i = 0; i < m.length; i++) m[i] = hash[i]
// const keypair = nacl.sign.keyPair.fromSeed(m)
/**
* {
publicKey: '0x10d15cb4a3747d9bcf6339ef7b1d8462e86da595e7da3f4dd17bb1b7e3b43cf9c67e41a439ec1ddae15e697b71bbfa2c4f662fce5105fc21c404df9ddae513f7',
privateKey: '5c3e9a13ff5618cca46bdf5780c4391e89af27eeea044c90ad9684f4fb51c453'
}
*/
const keypair =sm2.generateKeyPairHex(secret)
let sigValueHex = sm2.doSignature(secret, keypair.privateKey)
let verifyResult = sm2.doVerifySignature(secret, sigValueHex, keypair.publicKey)
console.log(verifyResult)
return {
publicKey: (keypair.publicKey),
privateKey: (keypair.privateKey)
}
}
function bufToHex(data) {
return Buffer.from(data).toString('hex')
}
console.log(getKeys("enter boring shaft rent essence foil trick vibrant fabric quote indoor output"))
const sm2 = require('sm-crypto').sm2
function getKeys(secret) {
// const hash = createHash(Buffer.from(secret))
// const m = new Uint8Array(nacl.sign.seedLength)
// for (let i = 0; i < m.length; i++) m[i] = hash[i]
// const keypair = nacl.sign.keyPair.fromSeed(m)
/**
* {
publicKey: '0x10d15cb4a3747d9bcf6339ef7b1d8462e86da595e7da3f4dd17bb1b7e3b43cf9c67e41a439ec1ddae15e697b71bbfa2c4f662fce5105fc21c404df9ddae513f7',
privateKey: '5c3e9a13ff5618cca46bdf5780c4391e89af27eeea044c90ad9684f4fb51c453'
}
*/
const hash=sm3(secret)
const keypair =sm2.generateKeyPairHexByHashValue(hash)
let sigValueHex = sm2.doSignature(secret, keypair.privateKey)
let verifyResult = sm2.doVerifySignature(secret, sigValueHex, keypair.publicKey)
console.log(verifyResult)
return {
publicKey: (keypair.publicKey),
privateKey: (keypair.privateKey)
}
}
function bufToHex(data) {
return Buffer.from(data).toString('hex')
}
console.log(getKeys("enter boring shaft rent essence foil trick vibrant fabric quote indoor output"))
const SM = require('sm-crypto')
function getKeys(secret) {
// const hash = createHash(Buffer.from(secret))
// const m = new Uint8Array(nacl.sign.seedLength)
// for (let i = 0; i < m.length; i++) m[i] = hash[i]
// const keypair = nacl.sign.keyPair.fromSeed(m)
/**
* {
publicKey: '0x10d15cb4a3747d9bcf6339ef7b1d8462e86da595e7da3f4dd17bb1b7e3b43cf9c67e41a439ec1ddae15e697b71bbfa2c4f662fce5105fc21c404df9ddae513f7',
privateKey: '5c3e9a13ff5618cca46bdf5780c4391e89af27eeea044c90ad9684f4fb51c453'
}
*/
const hash=SM.sm3(secret)
const keypair =SM.sm2.generateKeyPairHexByHashValue(hash)
let sigValueHex = SM.sm2.doSignature(secret, keypair.privateKey)
let verifyResult = SM.sm2.doVerifySignature(secret, sigValueHex, keypair.publicKey)
console.log(verifyResult)
return {
publicKey: (keypair.publicKey),
privateKey: (keypair.privateKey)
}
}
function bufToHex(data) {
return Buffer.from(data).toString('hex')
}
console.log(getKeys("enter boring shaft rent essence foil trick vibrant fabric quote indoor output"))
const SM = require('./src')
function getKeys(secret) {
// const hash = createHash(Buffer.from(secret))
// const m = new Uint8Array(nacl.sign.seedLength)
// for (let i = 0; i < m.length; i++) m[i] = hash[i]
// const keypair = nacl.sign.keyPair.fromSeed(m)
/**
* {
publicKey: '0x10d15cb4a3747d9bcf6339ef7b1d8462e86da595e7da3f4dd17bb1b7e3b43cf9c67e41a439ec1ddae15e697b71bbfa2c4f662fce5105fc21c404df9ddae513f7',
privateKey: '5c3e9a13ff5618cca46bdf5780c4391e89af27eeea044c90ad9684f4fb51c453'
}
*/
const hash=SM.sm3(secret)
const keypair =SM.sm2.generateKeyPairHexByHashValue(hash)
let sigValueHex = SM.sm2.doSignature(secret, keypair.privateKey)
let verifyResult = SM.sm2.doVerifySignature(secret, sigValueHex, keypair.publicKey)
console.log(verifyResult)
return {
publicKey: (keypair.publicKey),
privateKey: (keypair.privateKey)
}
}
function bufToHex(data) {
return Buffer.from(data).toString('hex')
}
console.log(getKeys("enter boring shaft rent essence foil trick vibrant fabric quote indoor output"))
.DS_Store
.idea
node_modules
npm-debug.log
package-lock.json
docs
test
\ No newline at end of file
Copyright © 2018 june01
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
# sm-crypto
国密算法sm2、sm3和sm4的js版。
> PS: 小程序移植版:[https://github.com/wechat-miniprogram/sm-crypto](https://github.com/wechat-miniprogram/sm-crypto)
## 安装
```bash
npm install --save @ddn/sm-crypto
```
## sm2
### 获取密钥对
```js
const sm2 = require('@ddn/sm-crypto').sm2;
let keypair = sm2.generateKeyPairHex();
publicKey = keypair.publicKey; // 公钥
privateKey = keypair.privateKey; // 私钥
```
### 获取密钥对根据hash
```js
const sm2 = require('@ddn/sm-crypto').sm2;
const secret='enter boring shaft rent essence foil trick vibrant fabric quote indoor output'
let keypair = sm2.generateKeyPairHex();
publicKey = keypair.publicKey; // 公钥
privateKey = keypair.privateKey; // 私钥
```
### 加密解密
```js
const sm2 = require('@ddn/sm-crypto').sm2;
const cipherMode = 1; // 1 - C1C3C2,0 - C1C2C3,默认为1
let encryptData = sm2.doEncrypt(msgString, publicKey, cipherMode); // 加密结果
let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode); // 解密结果
```
### 签名验签
> ps:理论上来说,只做纯签名是最快的。
```js
const sm2 = require('@ddn/sm-crypto').sm2;
// 纯签名 + 生成椭圆曲线点
let sigValueHex = sm2.doSignature(msg, privateKey); // 签名
let verifyResult = sm2.doVerifySignature(msg, sigValueHex, publicKey); // 验签结果
// 纯签名
let sigValueHex2 = sm2.doSignature(msg, privateKey, {
pointPool: [sm2.getPoint(), sm2.getPoint(), sm2.getPoint(), sm2.getPoint()], // 传入事先已生成好的椭圆曲线点,可加快签名速度
}); // 签名
let verifyResult2 = sm2.doVerifySignature(msg, sigValueHex2, publicKey); // 验签结果
// 纯签名 + 生成椭圆曲线点 + der编解码
let sigValueHex3 = sm2.doSignature(msg, privateKey, {
der: true,
}); // 签名
let verifyResult3 = sm2.doVerifySignature(msg, sigValueHex3, publicKey, {
der: true,
}); // 验签结果
// 纯签名 + 生成椭圆曲线点 + sm3杂凑
let sigValueHex4 = sm2.doSignature(msg, privateKey, {
hash: true,
}); // 签名
let verifyResult4 = sm2.doVerifySignature(msg, sigValueHex4, publicKey, {
hash: true,
}); // 验签结果
// 纯签名 + 生成椭圆曲线点 + sm3杂凑(不做公钥推导)
let sigValueHex5 = sm2.doSignature(msg, privateKey, {
hash: true,
publicKey, // 传入公钥的话,可以去掉sm3杂凑中推导公钥的过程,速度会比纯签名 + 生成椭圆曲线点 + sm3杂凑快
});
let verifyResult5 = sm2.doVerifySignature(msg, sigValueHex5, publicKey, {
hash: true,
publicKey,
});
```
### 获取椭圆曲线点
```js
const sm2 = require('@ddn/sm-crypto').sm2;
let poin = sm2.getPoint(); // 获取一个椭圆曲线点,可在sm2签名时传入
```
## sm3
```js
const sm3 = require('@ddn/sm-crypto').sm3;
let hashData = sm3('abc'); // 杂凑
```
## sm4
### 加密
```js
const sm4 = require('@ddn/sm-crypto').sm4;
const key = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10];
let encryptData = sm4.encrypt([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10], key); // 加密
```
### 解密
```js
const sm4 = require('@ddn/sm-crypto').sm4;
const key = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10];
let decryptData = sm4.decrypt([0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46], key); // 解密
```
## 协议
MIT
This diff is collapsed. Click to expand it.
window.sm3=function(n){function r(u){if(t[u])return t[u].exports;var e=t[u]={i:u,l:!1,exports:{}};return n[u].call(e.exports,e,e.exports,r),e.l=!0,e.exports}var t={};return r.m=n,r.c=t,r.d=function(n,t,u){r.o(n,t)||Object.defineProperty(n,t,{configurable:!1,enumerable:!0,get:u})},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(t,"a",t),t},r.o=function(n,r){return Object.prototype.hasOwnProperty.call(n,r)},r.p="",r(r.s=7)}({7:function(n,r,t){"use strict";function u(n,r){return n.length>=r?n:new Array(r-n.length+1).join("0")+n}function e(n){for(var r="",t=0;t<n.length/8;t++)r+=u(parseInt(n.substr(8*t,8),2).toString(16),2);return r}function o(n){for(var r="",t=0;t<n.length/2;t++)r+=u(parseInt(n.substr(2*t,2),16).toString(2),8);return r}function i(n){for(var r="",t=0,e=n.length;t<e;t++){r+=u(n[t].codePointAt(0).toString(2),8)}return r}function f(n,r){return n.substring(r%n.length)+n.substr(0,r%n.length)}function c(n,r,t){for(var u=n||"",e=r||"",o=[],i=void 0,f=u.length-1;f>=0;f--)i=t(u[f],e[f],i),o[f]=i[0];return o.join("")}function a(n,r){return c(n,r,function(n,r){return[n===r?"0":"1"]})}function s(n,r){return c(n,r,function(n,r){return["1"===n&&"1"===r?"1":"0"]})}function v(n,r){return c(n,r,function(n,r){return["1"===n||"1"===r?"1":"0"]})}function l(n,r){return c(n,r,function(n,r,t){var u=t?t[1]:"0";return n!==r?["0"===u?"1":"0",u]:[u,n]})}function d(n){return c(n,void 0,function(n){return["1"===n?"0":"1"]})}function g(n){return function(){for(var r=arguments.length,t=Array(r),u=0;u<r;u++)t[u]=arguments[u];return t.reduce(function(r,t){return n(r,t)})}}function p(n){return g(a)(n,f(n,9),f(n,17))}function b(n){return g(a)(n,f(n,15),f(n,23))}function h(n,r,t,u){return u>=0&&u<=15?g(a)(n,r,t):g(v)(s(n,r),s(n,t),s(r,t))}function x(n,r,t,u){return u>=0&&u<=15?g(a)(n,r,t):v(s(n,r),s(d(n),t))}function j(n){return o(n>=0&&n<=15?"79cc4519":"7a879d8a")}function y(n,r){for(var t=[],u=[],e=0;e<16;e++)t.push(r.substr(32*e,32));for(var o=16;o<68;o++)t.push(g(a)(b(g(a)(t[o-16],t[o-9],f(t[o-3],15))),f(t[o-13],7),t[o-6]));for(var i=0;i<64;i++)u.push(a(t[i],t[i+4]));for(var c=[],s=0;s<8;s++)c.push(n.substr(32*s,32));for(var v=c[0],d=c[1],y=c[2],S=c[3],w=c[4],m=c[5],A=c[6],O=c[7],P=void 0,I=void 0,_=void 0,M=void 0,k=0;k<64;k++)P=f(g(l)(f(v,12),w,f(j(k),k)),7),I=a(P,f(v,12)),_=g(l)(h(v,d,y,k),S,I,u[k]),M=g(l)(x(w,m,A,k),O,P,t[k]),S=y,y=f(d,9),d=v,v=_,O=A,A=f(m,19),m=w,w=p(M);return a([v,d,y,S,w,m,A,O].join(""),n)}n.exports=function(n){var r=i(n),t=r.length,f=t%512;f=f>=448?512-f%448-1:448-f-1;for(var c=(r+"1"+u("",f)+u(t.toString(2),64)).toString(),a=(t+f+65)/512,s=o("7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e"),v=0;v<=a-1;v++){s=y(s,c.substr(512*v,512))}return e(s)}}});
\ No newline at end of file
window.sm4=function(r){function n(e){if(t[e])return t[e].exports;var o=t[e]={i:e,l:!1,exports:{}};return r[e].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var t={};return n.m=r,n.c=t,n.d=function(r,t,e){n.o(r,t)||Object.defineProperty(r,t,{configurable:!1,enumerable:!0,get:e})},n.n=function(r){var t=r&&r.__esModule?function(){return r.default}:function(){return r};return n.d(t,"a",t),t},n.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},n.p="",n(n.s=8)}({8:function(r,n,t){"use strict";function e(r,n){return r<<n|r>>>32-n}function o(r){return(255&l[r>>>24&255])<<24|(255&l[r>>>16&255])<<16|(255&l[r>>>8&255])<<8|255&l[255&r]}function u(r){return r^e(r,2)^e(r,10)^e(r,18)^e(r,24)}function f(r){return r^e(r,13)^e(r,23)}function i(r,n,t){for(var e=void 0,f=void 0,i=new Array(4),c=new Array(4),a=0;a<4;a++)c[0]=255&r[0+4*a],c[1]=255&r[1+4*a],c[2]=255&r[2+4*a],c[3]=255&r[3+4*a],i[a]=c[0]<<24|c[1]<<16|c[2]<<8|c[3];for(e=0;e<32;e+=4)f=i[1]^i[2]^i[3]^t[e+0],f=o(f),i[0]^=u(f),f=i[2]^i[3]^i[0]^t[e+1],f=o(f),i[1]^=u(f),f=i[3]^i[0]^i[1]^t[e+2],f=o(f),i[2]^=u(f),f=i[0]^i[1]^i[2]^t[e+3],f=o(f),i[3]^=u(f);for(var v=0;v<16;v+=4)n[v]=i[3-v/4]>>>24&255,n[v+1]=i[3-v/4]>>>16&255,n[v+2]=i[3-v/4]>>>8&255,n[v+3]=255&i[3-v/4]}function c(r,n,t){for(var e=void 0,u=void 0,i=new Array(4),c=new Array(4),a=0;a<4;a++)c[0]=255&r[0+4*a],c[1]=255&r[1+4*a],c[2]=255&r[2+4*a],c[3]=255&r[3+4*a],i[a]=c[0]<<24|c[1]<<16|c[2]<<8|c[3];for(i[0]^=2746333894,i[1]^=1453994832,i[2]^=1736282519,i[3]^=2993693404,e=0;e<32;e+=4)u=i[1]^i[2]^i[3]^y[e+0],u=o(u),n[e+0]=i[0]^=f(u),u=i[2]^i[3]^i[0]^y[e+1],u=o(u),n[e+1]=i[1]^=f(u),u=i[3]^i[0]^i[1]^y[e+2],u=o(u),n[e+2]=i[2]^=f(u),u=i[0]^i[1]^i[2]^y[e+3],u=o(u),n[e+3]=i[3]^=f(u);if(t===v)for(e=0;e<16;e++)u=n[e],n[e]=n[31-e],n[31-e]=u}function a(r,n,t){var e=[],o=0,u=new Array(p);c(n,u,t);for(var f=new Array(16),a=new Array(16),v=r.length;v>=s;){f=r.slice(o,o+16),i(f,a,u);for(var l=0;l<s;l++)e[o+l]=a[l];v-=s,o+=s}return e}var v=0,p=32,s=16,l=[214,144,233,254,204,225,61,183,22,182,20,194,40,251,44,5,43,103,154,118,42,190,4,195,170,68,19,38,73,134,6,153,156,66,80,244,145,239,152,122,51,84,11,67,237,207,172,98,228,179,28,169,201,8,232,149,128,223,148,250,117,143,63,166,71,7,167,252,243,115,23,186,131,89,60,25,230,133,79,168,104,107,129,178,113,100,218,139,248,235,15,75,112,86,157,53,30,36,14,94,99,88,209,162,37,34,124,59,1,33,120,135,212,0,70,87,159,211,39,82,76,54,2,231,160,196,200,158,234,191,138,210,64,199,56,181,163,247,242,206,249,97,21,161,224,174,93,164,155,52,26,85,173,147,50,48,245,140,177,227,29,246,226,46,130,102,202,96,192,41,35,171,13,83,78,111,213,219,55,69,222,253,142,47,3,255,106,114,109,108,91,81,141,27,175,146,187,221,188,127,17,217,92,65,31,16,90,216,10,193,49,136,165,205,123,189,45,116,208,18,184,229,180,176,137,105,151,74,12,150,119,126,101,185,241,9,197,110,198,132,24,240,125,236,58,220,77,32,121,238,95,62,215,203,57,72],y=[462357,472066609,943670861,1415275113,1886879365,2358483617,2830087869,3301692121,3773296373,4228057617,404694573,876298825,1347903077,1819507329,2291111581,2762715833,3234320085,3705924337,4177462797,337322537,808926789,1280531041,1752135293,2223739545,2695343797,3166948049,3638552301,4110090761,269950501,741554753,1213159005,1684763257];r.exports={encrypt:function(r,n){return a(r,n,1)},decrypt:function(r,n){return a(r,n,0)}}}});
\ No newline at end of file
No preview for this file type
No preview for this file type
No preview for this file type
{
"name": "@ddn/sm-crypto",
"version": "0.0.1",
"description": "@ddn/sm-crypto,基于sm-crypto。",
"main": "dist/index.js",
"scripts": {
"prepublish": "npm run build",
"test": "jest ./test/*",
"lint": "eslint \"src/**/*.js\" --fix",
"build": "npm run lint && webpack"
},
"repository": {
"type": "git",
"url": "git+https://github.com/ddnlink"
},
"files": [
"dist",
"README.md"
],
"keywords": [
"ddn",
"sm",
"js",
"crypto"
],
"jest": {
"testEnvironment": "jsdom",
"testURL": "https://jest.test"
},
"author": "creazy",
"license": "MIT",
"dependencies": {
"jsbn": "^1.1.0"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.24.1",
"jest": "^22.1.4",
"webpack": "^3.10.0",
"eslint": "^5.3.0",
"eslint-config-airbnb-base": "13.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-node": "^7.0.1",
"eslint-plugin-promise": "^3.8.0"
}
}
module.exports = {
sm2: require('./sm2/index'),
sm3: require('./sm3/index'),
sm4: require('./sm4/index'),
}
/* eslint-disable class-methods-use-this */
const {BigInteger} = require('jsbn')
function bigIntToMinTwosComplementsHex(bigIntegerValue) {
let h = bigIntegerValue.toString(16)
if (h.substr(0, 1) !== '-') {
if (h.length % 2 === 1) {
h = '0' + h
} else if (!h.match(/^[0-7]/)) {
h = '00' + h
}
} else {
const hPos = h.substr(1)
let xorLen = hPos.length
if (xorLen % 2 === 1) {
xorLen += 1
} else if (!h.match(/^[0-7]/)) {
xorLen += 2
}
let hMask = ''
for (let i = 0; i < xorLen; i++) {
hMask += 'f'
}
const biMask = new BigInteger(hMask, 16)
const biNeg = biMask.xor(bigIntegerValue).add(BigInteger.ONE)
h = biNeg.toString(16).replace(/^-/, '')
}
return h
}
/**
* base class for ASN.1 DER encoder object
*/
class ASN1Object {
constructor() {
this.isModified = true
this.hTLV = null
this.hT = '00'
this.hL = '00'
this.hV = ''
}
/**
* get hexadecimal ASN.1 TLV length(L) bytes from TLV value(V)
*/
getLengthHexFromValue() {
const n = this.hV.length / 2
let hN = n.toString(16)
if (hN.length % 2 === 1) {
hN = '0' + hN
}
if (n < 128) {
return hN
} else {
const hNlen = hN.length / 2
const head = 128 + hNlen
return head.toString(16) + hN
}
}
/**
* get hexadecimal string of ASN.1 TLV bytes
*/
getEncodedHex() {
if (this.hTLV == null || this.isModified) {
this.hV = this.getFreshValueHex()
this.hL = this.getLengthHexFromValue()
this.hTLV = this.hT + this.hL + this.hV
this.isModified = false
}
return this.hTLV
}
getFreshValueHex() {
return ''
}
}
/**
* class for ASN.1 DER Integer
*/
class DERInteger extends ASN1Object {
constructor(options) {
super()
this.hT = '02'
if (options && options.bigint) {
this.hTLV = null
this.isModified = true
this.hV = bigIntToMinTwosComplementsHex(options.bigint)
}
}
getFreshValueHex() {
return this.hV
}
}
/**
* class for ASN.1 DER Sequence
*/
class DERSequence extends ASN1Object {
constructor(options) {
super()
this.hT = '30'
this.asn1Array = []
if (options && options.array) {
this.asn1Array = options.array
}
}
getFreshValueHex() {
let h = ''
for (let i = 0; i < this.asn1Array.length; i++) {
const asn1Obj = this.asn1Array[i]
h += asn1Obj.getEncodedHex()
}
this.hV = h
return this.hV
}
}
/**
* get byte length for ASN.1 L(length) bytes
*/
function getByteLengthOfL(s, pos) {
if (s.substring(pos + 2, pos + 3) !== '8') return 1
const i = parseInt(s.substring(pos + 3, pos + 4), 10)
if (i === 0) return -1 // length octet '80' indefinite length
if (i > 0 && i < 10) return i + 1 // including '8?' octet;
return -2 // malformed format
}
/**
* get hexadecimal string for ASN.1 L(length) bytes
*/
function getHexOfL(s, pos) {
const len = getByteLengthOfL(s, pos)
if (len < 1) return ''
return s.substring(pos + 2, pos + 2 + len * 2)
}
/**
* get integer value of ASN.1 length for ASN.1 data
*/
function getIntOfL(s, pos) {
const hLength = getHexOfL(s, pos)
if (hLength === '') return -1
let bi
if (parseInt(hLength.substring(0, 1), 10) < 8) {
bi = new BigInteger(hLength, 16)
} else {
bi = new BigInteger(hLength.substring(2), 16)
}
return bi.intValue()
}
/**
* get ASN.1 value starting string position for ASN.1 object refered by index 'idx'.
*/
function getStartPosOfV(s, pos) {
const lLen = getByteLengthOfL(s, pos)
if (lLen < 0) return lLen
return pos + (lLen + 1) * 2
}
/**
* get hexadecimal string of ASN.1 V(value)
*/
function getHexOfV(s, pos) {
const pos1 = getStartPosOfV(s, pos)
const len = getIntOfL(s, pos)
return s.substring(pos1, pos1 + len * 2)
}
/**
* get next sibling starting index for ASN.1 object string
*/
function getPosOfNextSibling(s, pos) {
const pos1 = getStartPosOfV(s, pos)
const len = getIntOfL(s, pos)
return pos1 + len * 2
}
/**
* get array of indexes of child ASN.1 objects
*/
function getPosArrayOfChildren(h, pos) {
const a = []
const p0 = getStartPosOfV(h, pos)
a.push(p0)
const len = getIntOfL(h, pos)
let p = p0
let k = 0
for (;;) {
const pNext = getPosOfNextSibling(h, p)
if (pNext == null || (pNext - p0 >= (len * 2))) break
if (k >= 200) break
a.push(pNext)
p = pNext
k++
}
return a
}
module.exports = {
/**
* ASN.1 DER编码
*/
encodeDer(r, s) {
const derR = new DERInteger({bigint: r})
const derS = new DERInteger({bigint: s})
const derSeq = new DERSequence({array: [derR, derS]})
return derSeq.getEncodedHex()
},
/**
* 解析 ASN.1 DER
*/
decodeDer(input) {
// 1. Items of ASN.1 Sequence Check
const a = getPosArrayOfChildren(input, 0)
// 2. Integer check
const iTLV1 = a[0]
const iTLV2 = a[1]
// 3. getting value
const hR = getHexOfV(input, iTLV1)
const hS = getHexOfV(input, iTLV2)
const r = new BigInteger(hR, 16)
const s = new BigInteger(hS, 16)
return {r, s}
}
}
/* eslint-disable no-case-declarations, max-len */
const {BigInteger} = require('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(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:
// 不支持的压缩方式
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)))
default:
// 不支持
return null
}
}
}
module.exports = {
ECPointFp,
ECCurveFp,
}
/* eslint-disable no-use-before-define */
const {BigInteger} = require('jsbn')
const {encodeDer, decodeDer} = require('./asn1')
const SM3Digest = require('./sm3')
const SM2Cipher = require('./sm2')
const _ = require('./utils')
const {G, curve, n} = _.generateEcparam()
const C1C2C3 = 0
/**
* 加密
*/
function doEncrypt(msg, publicKey, cipherMode = 1) {
const cipher = new SM2Cipher()
msg = _.hexToArray(_.parseUtf8StringToHex(msg))
if (publicKey.length > 128) {
publicKey = publicKey.substr(publicKey.length - 128)
}
const xHex = publicKey.substr(0, 64)
const yHex = publicKey.substr(64)
publicKey = cipher.createPoint(xHex, yHex)
const c1 = cipher.initEncipher(publicKey)
cipher.encryptBlock(msg)
const c2 = _.arrayToHex(msg)
let c3 = new Array(32)
cipher.doFinal(c3)
c3 = _.arrayToHex(c3)
return cipherMode === C1C2C3 ? c1 + c2 + c3 : c1 + c3 + c2
}
/**
* 解密
*/
function doDecrypt(encryptData, privateKey, cipherMode = 1) {
const cipher = new SM2Cipher()
privateKey = new BigInteger(privateKey, 16)
const c1X = encryptData.substr(0, 64)
const c1Y = encryptData.substr(0 + c1X.length, 64)
const c1Length = c1X.length + c1Y.length
let c3 = encryptData.substr(c1Length, 64)
let c2 = encryptData.substr(c1Length + 64)
if (cipherMode === C1C2C3) {
c3 = encryptData.substr(encryptData.length - 64)
c2 = encryptData.substr(c1Length, encryptData.length - c1Length - 64)
}
const data = _.hexToArray(c2)
const c1 = cipher.createPoint(c1X, c1Y)
cipher.initDecipher(privateKey, c1)
cipher.decryptBlock(data)
const c3_ = new Array(32)
cipher.doFinal(c3_)
const isDecrypt = _.arrayToHex(c3_) === c3
if (isDecrypt) {
const decryptData = _.arrayToUtf8(data)
return decryptData
} else {
return ''
}
}
/**
* 签名
*/
function doSignature(msg, privateKey, {
pointPool, der, hash, publicKey
} = {}) {
let hashHex = typeof msg === 'string' ? _.parseUtf8StringToHex(msg) : _.parseArrayBufferToHex(msg)
if (hash) {
// sm3杂凑
publicKey = publicKey || getPublicKeyFromPrivateKey(privateKey)
hashHex = doSm3Hash(hashHex, publicKey)
}
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) {
// asn1 der编码
return encodeDer(r, s)
}
return _.leftPad(r.toString(16), 64) + _.leftPad(s.toString(16), 64)
}
/**
* 验签
*/
function doVerifySignature(msg, signHex, publicKey, {der, hash} = {}) {
let hashHex = typeof msg === 'string' ? _.parseUtf8StringToHex(msg) : _.parseArrayBufferToHex(msg)
if (hash) {
// sm3杂凑
hashHex = doSm3Hash(hashHex, publicKey)
}
let r; let
s
if (der) {
const decodeDerObj = decodeDer(signHex)
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 doSm3Hash(hashHex, publicKey) {
const smDigest = new SM3Digest()
const z = new SM3Digest().getZ(G, publicKey.substr(2, 128))
const zValue = _.hexToArray(_.arrayToHex(z).toString())
const p = hashHex
const pValue = _.hexToArray(p)
const hashData = new Array(smDigest.getDigestSize())
smDigest.blockUpdate(zValue, 0, zValue.length)
smDigest.blockUpdate(pValue, 0, pValue.length)
smDigest.doFinal(hashData, 0)
return _.arrayToHex(hashData).toString()
}
/**
* 计算公钥
*/
function getPublicKeyFromPrivateKey(privateKey) {
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 = _.generateKeyPairHex()
const PA = curve.decodePointHex(keypair.publicKey)
keypair.k = new BigInteger(keypair.privateKey, 16)
keypair.x1 = PA.getX().toBigInteger()
return keypair
}
module.exports = {
generateKeyPairHex: _.generateKeyPairHex,
generateKeyPairHexBySecret: _.generateKeyPairHexBySecret,
doEncrypt,
doDecrypt,
doSignature,
doVerifySignature,
getPoint,
}
/* eslint-disable no-bitwise, no-mixed-operators, class-methods-use-this */
const {BigInteger} = require('jsbn')
const SM3Digest = require('./sm3')
const _ = require('./utils')
class SM2Cipher {
constructor() {
this.ct = 1
this.p2 = null
this.sm3keybase = null
this.sm3c3 = null
this.key = new Array(32)
this.keyOff = 0
}
reset() {
this.sm3keybase = new SM3Digest()
this.sm3c3 = new SM3Digest()
const xWords = _.hexToArray(this.p2.getX().toBigInteger().toRadix(16))
const yWords = _.hexToArray(this.p2.getY().toBigInteger().toRadix(16))
this.sm3keybase.blockUpdate(xWords, 0, xWords.length)
this.sm3c3.blockUpdate(xWords, 0, xWords.length)
this.sm3keybase.blockUpdate(yWords, 0, yWords.length)
this.ct = 1
this.nextKey()
}
nextKey() {
const sm3keycur = new SM3Digest(this.sm3keybase)
sm3keycur.update((this.ct >> 24 & 0x00ff))
sm3keycur.update((this.ct >> 16 & 0x00ff))
sm3keycur.update((this.ct >> 8 & 0x00ff))
sm3keycur.update((this.ct & 0x00ff))
sm3keycur.doFinal(this.key, 0)
this.keyOff = 0
this.ct++
}
initEncipher(userKey) {
const keypair = _.generateKeyPairHex()
const k = new BigInteger(keypair.privateKey, 16)
let publicKey = keypair.publicKey
this.p2 = userKey.multiply(k) // [k](Pb)
this.reset()
if (publicKey.length > 128) {
publicKey = publicKey.substr(publicKey.length - 128)
}
return publicKey
}
encryptBlock(data) {
this.sm3c3.blockUpdate(data, 0, data.length)
for (let i = 0; i < data.length; i++) {
if (this.keyOff === this.key.length) {
this.nextKey()
}
data[i] ^= this.key[this.keyOff++] & 0xff
}
}
initDecipher(userD, c1) {
this.p2 = c1.multiply(userD)
this.reset()
}
decryptBlock(data) {
for (let i = 0; i < data.length; i++) {
if (this.keyOff === this.key.length) {
this.nextKey()
}
data[i] ^= this.key[this.keyOff++] & 0xff
}
this.sm3c3.blockUpdate(data, 0, data.length)
}
doFinal(c3) {
const yWords = _.hexToArray(this.p2.getY().toBigInteger().toRadix(16))
this.sm3c3.blockUpdate(yWords, 0, yWords.length)
this.sm3c3.doFinal(c3, 0)
this.reset()
}
createPoint(x, y) {
const publicKey = '04' + x + y
const point = _.getGlobalCurve().decodePointHex(publicKey)
return point
}
}
module.exports = SM2Cipher
/* eslint-disable no-bitwise, no-mixed-operators, class-methods-use-this, camelcase */
const {BigInteger} = require('jsbn')
const _ = require('./utils')
const copyArray = function (sourceArray, sourceIndex, destinationArray, destinationIndex, length) {
for (let i = 0; i < length; i++) {
destinationArray[destinationIndex + i] = sourceArray[sourceIndex + i]
}
}
const Int32 = {
minValue: -0b10000000000000000000000000000000,
maxValue: 0b1111111111111111111111111111111,
parse(n) {
if (n < this.minValue) {
const bigInteger = Number(-n)
const bigIntegerRadix = bigInteger.toString(2)
const subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 31, 31)
let reBigIntegerRadix = ''
for (let i = 0; i < subBigIntegerRadix.length; i++) {
const subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1)
reBigIntegerRadix += subBigIntegerRadixItem === '0' ? '1' : '0'
}
const result = parseInt(reBigIntegerRadix, 2)
return (result + 1)
} else if (n > this.maxValue) {
const bigInteger = Number(n)
const bigIntegerRadix = bigInteger.toString(2)
const subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 31, 31)
let reBigIntegerRadix = ''
for (let i = 0; i < subBigIntegerRadix.length; i++) {
const subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1)
reBigIntegerRadix += subBigIntegerRadixItem === '0' ? '1' : '0'
}
const result = parseInt(reBigIntegerRadix, 2)
return -(result + 1)
} else {
return n
}
},
parseByte(n) {
if (n < 0) {
const bigInteger = Number(-n)
const bigIntegerRadix = bigInteger.toString(2)
const subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 8, 8)
let reBigIntegerRadix = ''
for (let i = 0; i < subBigIntegerRadix.length; i++) {
const subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1)
reBigIntegerRadix += subBigIntegerRadixItem === '0' ? '1' : '0'
}
const result = parseInt(reBigIntegerRadix, 2)
return (result + 1) % 256
} else if (n > 255) {
const bigInteger = Number(n)
const bigIntegerRadix = bigInteger.toString(2)
return parseInt(bigIntegerRadix.substr(bigIntegerRadix.length - 8, 8), 2)
} else {
return n
}
}
}
class SM3Digest {
constructor(...args) {
this.xBuf = []
this.xBufOff = 0
this.byteCount = 0
this.DIGEST_LENGTH = 32
this.v0 = [0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600,
0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e]
this.v0 = [0x7380166f, 0x4914b2b9, 0x172442d7, -628488704,
-1452330820, 0x163138aa, -477237683, -1325724082]
this.v = new Array(8)
this.v_ = new Array(8)
this.X0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
this.X = new Array(68)
this.xOff = 0
this.T_00_15 = 0x79cc4519
this.T_16_63 = 0x7a879d8a
if (args.length > 0) {
this.initDigest(args[0])
} else {
this.init()
}
}
init() {
this.xBuf = new Array(4)
this.reset()
}
initDigest(t) {
this.xBuf = [].concat(t.xBuf)
this.xBufOff = t.xBufOff
this.byteCount = t.byteCount
copyArray(t.X, 0, this.X, 0, t.X.length)
this.xOff = t.xOff
copyArray(t.v, 0, this.v, 0, t.v.length)
}
getDigestSize() {
return this.DIGEST_LENGTH
}
reset() {
this.byteCount = 0
this.xBufOff = 0
const keys = Object.keys(this.xBuf)
for (let i = 0, len = keys.length; i < len; i++) this.xBuf[keys[i]] = null
copyArray(this.v0, 0, this.v, 0, this.v0.length)
this.xOff = 0
copyArray(this.X0, 0, this.X, 0, this.X0.length)
}
processBlock() {
let i
const ww = this.X
const ww_ = new Array(64)
for (i = 16; i < 68; i++) {
ww[i] = this.p1(ww[i - 16] ^ ww[i - 9] ^ (this.rotate(ww[i - 3], 15))) ^ (this.rotate(ww[i - 13], 7)) ^ ww[i - 6]
}
for (i = 0; i < 64; i++) {
ww_[i] = ww[i] ^ ww[i + 4]
}
const vv = this.v
const vv_ = this.v_
copyArray(vv, 0, vv_, 0, this.v0.length)
let SS1
let SS2
let TT1
let TT2
let aaa
for (i = 0; i < 16; i++) {
aaa = this.rotate(vv_[0], 12)
SS1 = Int32.parse(Int32.parse(aaa + vv_[4]) + this.rotate(this.T_00_15, i))
SS1 = this.rotate(SS1, 7)
SS2 = SS1 ^ aaa
TT1 = Int32.parse(Int32.parse(this.ff_00_15(vv_[0], vv_[1], vv_[2]) + vv_[3]) + SS2) + ww_[i]
TT2 = Int32.parse(Int32.parse(this.gg_00_15(vv_[4], vv_[5], vv_[6]) + vv_[7]) + SS1) + ww[i]
vv_[3] = vv_[2]
vv_[2] = this.rotate(vv_[1], 9)
vv_[1] = vv_[0]
vv_[0] = TT1
vv_[7] = vv_[6]
vv_[6] = this.rotate(vv_[5], 19)
vv_[5] = vv_[4]
vv_[4] = this.p0(TT2)
}
for (i = 16; i < 64; i++) {
aaa = this.rotate(vv_[0], 12)
SS1 = Int32.parse(Int32.parse(aaa + vv_[4]) + this.rotate(this.T_16_63, i))
SS1 = this.rotate(SS1, 7)
SS2 = SS1 ^ aaa
TT1 = Int32.parse(Int32.parse(this.ff_16_63(vv_[0], vv_[1], vv_[2]) + vv_[3]) + SS2) + ww_[i]
TT2 = Int32.parse(Int32.parse(this.gg_16_63(vv_[4], vv_[5], vv_[6]) + vv_[7]) + SS1) + ww[i]
vv_[3] = vv_[2]
vv_[2] = this.rotate(vv_[1], 9)
vv_[1] = vv_[0]
vv_[0] = TT1
vv_[7] = vv_[6]
vv_[6] = this.rotate(vv_[5], 19)
vv_[5] = vv_[4]
vv_[4] = this.p0(TT2)
}
for (i = 0; i < 8; i++) {
vv[i] ^= Int32.parse(vv_[i])
}
this.xOff = 0
copyArray(this.X0, 0, this.X, 0, this.X0.length)
}
processWord(in_Renamed, inOff) {
let n = in_Renamed[inOff] << 24
n |= (in_Renamed[++inOff] & 0xff) << 16
n |= (in_Renamed[++inOff] & 0xff) << 8
n |= (in_Renamed[++inOff] & 0xff)
this.X[this.xOff] = n
if (++this.xOff === 16) {
this.processBlock()
}
}
processLength(bitLength) {
if (this.xOff > 14) {
this.processBlock()
}
this.X[14] = (this.urShiftLong(bitLength, 32))
this.X[15] = (bitLength & (0xffffffff))
}
intToBigEndian(n, bs, off) {
bs[off] = Int32.parseByte(this.urShift(n, 24)) & 0xff
bs[++off] = Int32.parseByte(this.urShift(n, 16)) & 0xff
bs[++off] = Int32.parseByte(this.urShift(n, 8)) & 0xff
bs[++off] = Int32.parseByte(n) & 0xff
}
doFinal(out_Renamed, outOff) {
this.finish()
for (let i = 0; i < 8; i++) {
this.intToBigEndian(this.v[i], out_Renamed, outOff + i * 4)
}
this.reset()
return this.DIGEST_LENGTH
}
update(input) {
this.xBuf[this.xBufOff++] = input
if (this.xBufOff === this.xBuf.length) {
this.processWord(this.xBuf, 0)
this.xBufOff = 0
}
this.byteCount++
}
blockUpdate(input, inOff, length) {
while ((this.xBufOff !== 0) && (length > 0)) {
this.update(input[inOff])
inOff++
length--
}
while (length > this.xBuf.length) {
this.processWord(input, inOff)
inOff += this.xBuf.length
length -= this.xBuf.length
this.byteCount += this.xBuf.length
}
while (length > 0) {
this.update(input[inOff])
inOff++
length--
}
}
finish() {
const bitLength = (this.byteCount << 3)
this.update((128))
while (this.xBufOff !== 0) this.update((0))
this.processLength(bitLength)
this.processBlock()
}
rotate(x, n) {
return (x << n) | (this.urShift(x, (32 - n)))
}
p0(X) {
return ((X) ^ this.rotate((X), 9) ^ this.rotate((X), 17))
}
p1(X) {
return ((X) ^ this.rotate((X), 15) ^ this.rotate((X), 23))
}
ff_00_15(X, Y, Z) {
return (X ^ Y ^ Z)
}
ff_16_63(X, Y, Z) {
return ((X & Y) | (X & Z) | (Y & Z))
}
gg_00_15(X, Y, Z) {
return (X ^ Y ^ Z)
}
gg_16_63(X, Y, Z) {
return ((X & Y) | (~X & Z))
}
urShift(number, bits) {
if (number > Int32.maxValue || number < Int32.minValue) {
number = Int32.parse(number)
}
return number >>> bits
}
urShiftLong(number, bits) {
let returnV
const big = new BigInteger()
big.fromInt(number)
if (big.signum() >= 0) {
returnV = big.shiftRight(bits).intValue()
} else {
const bigAdd = new BigInteger()
bigAdd.fromInt(2)
const shiftLeftBits = ~bits
let shiftLeftNumber = ''
if (shiftLeftBits < 0) {
const shiftRightBits = 64 + shiftLeftBits
for (let i = 0; i < shiftRightBits; i++) {
shiftLeftNumber += '0'
}
const shiftLeftNumberBigAdd = new BigInteger()
shiftLeftNumberBigAdd.fromInt(number >> bits)
const shiftLeftNumberBig = new BigInteger('10' + shiftLeftNumber, 2)
shiftLeftNumber = shiftLeftNumberBig.toRadix(10)
const r = shiftLeftNumberBig.add(shiftLeftNumberBigAdd)
returnV = r.toRadix(10)
} else {
shiftLeftNumber = bigAdd.shiftLeft((~bits)).intValue()
returnV = (number >> bits) + shiftLeftNumber
}
}
return returnV
}
getZ(g, publicKey) {
const userId = _.parseUtf8StringToHex('1234567812345678')
const len = userId.length * 4
this.update((len >> 8 & 0x00ff))
this.update((len & 0x00ff))
const userIdWords = _.hexToArray(userId)
this.blockUpdate(userIdWords, 0, userIdWords.length)
const aWords = _.hexToArray(g.curve.a.toBigInteger().toRadix(16))
const bWords = _.hexToArray(g.curve.b.toBigInteger().toRadix(16))
const gxWords = _.hexToArray(g.getX().toBigInteger().toRadix(16))
const gyWords = _.hexToArray(g.getY().toBigInteger().toRadix(16))
const pxWords = _.hexToArray(publicKey.substr(0, 64))
const pyWords = _.hexToArray(publicKey.substr(64, 64))
this.blockUpdate(aWords, 0, aWords.length)
this.blockUpdate(bWords, 0, bWords.length)
this.blockUpdate(gxWords, 0, gxWords.length)
this.blockUpdate(gyWords, 0, gyWords.length)
this.blockUpdate(pxWords, 0, pxWords.length)
this.blockUpdate(pyWords, 0, pyWords.length)
const md = new Array(this.getDigestSize())
this.doFinal(md, 0)
return md
}
}
module.exports = SM3Digest
/* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */
const {BigInteger, SecureRandom} = require('jsbn')
const {ECCurveFp} = require('./ec')
const SM3 = require('../sm3')
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}
}
/**
* 生成密钥对
*/
function generateKeyPairHex() {
const d = new BigInteger(n.bitLength(), rng).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}
}
/**
* 根据指定字符串,生成密钥对
* @param {String} secret
*/
function generateKeyPairHexBySecret(secret) {
const hashValue = SM3(secret)
const d = new BigInteger(hashValue, 16)
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 parseUtf8StringToHex(input) {
input = unescape(encodeURIComponent(input))
const length = input.length
// 转换到字数组
const words = []
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('')
}
/**
* 解析arrayBuffer到16进制字符串
*/
function parseArrayBufferToHex(input) {
return Array.prototype.map.call(new Uint8Array(input), x => ('00' + x.toString(16)).slice(-2)).join('')
}
/**
* 补全16进制字符串
*/
function leftPad(input, num) {
if (input.length >= num) return input
return (new Array(num - input.length + 1)).join('0') + input
}
/**
* 转成16进制串
*/
function arrayToHex(arr) {
const words = []
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++
}
// 转换到16进制
const hexChars = []
for (let i = 0; i < arr.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('')
}
/**
* 转成utf8串
*/
function arrayToUtf8(arr) {
const words = []
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')
}
}
/**
* 转成ascii码数组
*/
function hexToArray(hexStr) {
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
}
module.exports = {
getGlobalCurve,
generateEcparam,
generateKeyPairHex,
generateKeyPairHexBySecret,
parseUtf8StringToHex,
parseArrayBufferToHex,
leftPad,
arrayToHex,
arrayToUtf8,
hexToArray,
}
/**
* 左补0到指定长度
*/
function leftPad(input, num) {
if (input.length >= num) return input
return (new Array(num - input.length + 1)).join('0') + input
}
/**
* 二进制转化为十六进制
*/
function binary2hex(binary) {
const binaryLength = 8
let hex = ''
for (let i = 0; i < binary.length / binaryLength; i++) {
hex += leftPad(parseInt(binary.substr(i * binaryLength, binaryLength), 2).toString(16), 2)
}
return hex
}
/**
* 十六进制转化为二进制
*/
function hex2binary(hex) {
const hexLength = 2
let binary = ''
for (let i = 0; i < hex.length / hexLength; i++) {
binary += leftPad(parseInt(hex.substr(i * hexLength, hexLength), 16).toString(2), 8)
}
return binary
}
/**
* 普通字符串转化为二进制
*/
function str2binary(str) {
let binary = ''
for (let i = 0, len = str.length; i < len; i++) {
const ch = str[i]
binary += leftPad(ch.codePointAt(0).toString(2), 8)
}
return binary
}
/**
* 循环左移
*/
function rol(str, n) {
return str.substring(n % str.length) + str.substr(0, n % str.length)
}
/**
* 二进制运算
*/
function binaryCal(x, y, method) {
const a = x || ''
const b = y || ''
const result = []
let prevResult
for (let i = a.length - 1; i >= 0; i--) { // 大端
prevResult = method(a[i], b[i], prevResult)
result[i] = prevResult[0]
}
return result.join('')
}
/**
* 二进制异或运算
*/
function xor(x, y) {
return binaryCal(x, y, (a, b) => [(a === b ? '0' : '1')])
}
/**
* 二进制与运算
*/
function and(x, y) {
return binaryCal(x, y, (a, b) => [(a === '1' && b === '1' ? '1' : '0')])
}
/**
* 二进制或运算
*/
function or(x, y) {
return binaryCal(x, y, (a, b) => [(a === '1' || b === '1' ? '1' : '0')]) // a === '0' && b === '0' ? '0' : '1'
}
/**
* 二进制与运算
*/
function add(x, y) {
const result = binaryCal(x, y, (a, b, prevResult) => {
const carry = prevResult ? prevResult[1] : '0' || '0'
// a,b不等时,carry不变,结果与carry相反
// a,b相等时,结果等于原carry,新carry等于a
if (a !== b) return [carry === '0' ? '1' : '0', carry]
return [carry, a]
})
return result
}
/**
* 二进制非运算
*/
function not(x) {
return binaryCal(x, undefined, a => [a === '1' ? '0' : '1'])
}
function calMulti(method) {
return (...arr) => arr.reduce((prev, curr) => method(prev, curr))
}
/**
* 压缩函数中的置换函数 P1(X) = X xor (X <<< 9) xor (X <<< 17)
*/
function P0(X) {
return calMulti(xor)(X, rol(X, 9), rol(X, 17))
}
/**
* 消息扩展中的置换函数 P1(X) = X xor (X <<< 15) xor (X <<< 23)
*/
function P1(X) {
return calMulti(xor)(X, rol(X, 15), rol(X, 23))
}
function FF(X, Y, Z, j) {
return j >= 0 && j <= 15 ? calMulti(xor)(X, Y, Z) : calMulti(or)(and(X, Y), and(X, Z), and(Y, Z))
}
function GG(X, Y, Z, j) {
return j >= 0 && j <= 15 ? calMulti(xor)(X, Y, Z) : or(and(X, Y), and(not(X), Z))
}
function T(j) {
return j >= 0 && j <= 15 ? hex2binary('79cc4519') : hex2binary('7a879d8a')
}
/**
* 压缩函数
*/
function CF(V, Bi) {
// 消息扩展
const wordLength = 32
const W = []
const M = [] // W'
// 将消息分组B划分为16个字W0, W1,…… ,W15 (字为长度为32的比特串)
for (let i = 0; i < 16; i++) {
W.push(Bi.substr(i * wordLength, wordLength))
}
// 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(calMulti(xor)(
P1(calMulti(xor)(W[j - 16], W[j - 9], rol(W[j - 3], 15))),
rol(W[j - 13], 7),
W[j - 6]
))
}
// W′[j] = W[j] xor W[j+4]
for (let j = 0; j < 64; j++) {
M.push(xor(W[j], W[j + 4]))
}
// 压缩
const wordRegister = [] // 字寄存器
for (let j = 0; j < 8; j++) {
wordRegister.push(V.substr(j * wordLength, wordLength))
}
let A = wordRegister[0]
let B = wordRegister[1]
let C = wordRegister[2]
let D = wordRegister[3]
let E = wordRegister[4]
let F = wordRegister[5]
let G = wordRegister[6]
let H = wordRegister[7]
// 中间变量
let SS1
let SS2
let TT1
let TT2
for (let j = 0; j < 64; j++) {
SS1 = rol(calMulti(add)(rol(A, 12), E, rol(T(j), j)), 7)
SS2 = xor(SS1, rol(A, 12))
TT1 = calMulti(add)(FF(A, B, C, j), D, SS2, M[j])
TT2 = calMulti(add)(GG(E, F, G, j), H, SS1, W[j])
D = C
C = rol(B, 9)
B = A
A = TT1
H = G
G = rol(F, 19)
F = E
E = P0(TT2)
}
return xor([A, B, C, D, E, F, G, H].join(''), V)
}
module.exports = function (str) {
const binary = str2binary(str)
// 填充
const len = binary.length
// 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 m = `${binary}1${leftPad('', k)}${leftPad(len.toString(2), 64)}`.toString() // k个0
// 迭代压缩
const n = (len + k + 65) / 512
let V = hex2binary('7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e')
for (let i = 0; i <= n - 1; i++) {
const B = m.substr(512 * i, 512)
V = CF(V, B)
}
return binary2hex(V)
}
/* eslint-disable no-bitwise, no-mixed-operators */
const DECRYPT = 0
const ROUND = 32
const BLOCK = 16
const Sbox = [
0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
]
const CK = [
0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
]
function rotl(x, y) {
return x << y | x >>> (32 - y)
}
function byteSub(a) {
return (Sbox[a >>> 24 & 0xFF] & 0xFF) << 24 |
(Sbox[a >>> 16 & 0xFF] & 0xFF) << 16 |
(Sbox[a >>> 8 & 0xFF] & 0xFF) << 8 |
(Sbox[a & 0xFF] & 0xFF)
}
function l1(b) {
return b ^ rotl(b, 2) ^ rotl(b, 10) ^ rotl(b, 18) ^ rotl(b, 24)
}
function l2(b) {
return b ^ rotl(b, 13) ^ rotl(b, 23)
}
function sms4Crypt(input, output, roundKey) {
let r
let mid
const x = new Array(4)
const tmp = new Array(4)
for (let i = 0; i < 4; i++) {
tmp[0] = input[0 + 4 * i] & 0xff
tmp[1] = input[1 + 4 * i] & 0xff
tmp[2] = input[2 + 4 * i] & 0xff
tmp[3] = input[3 + 4 * i] & 0xff
x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3]
}
for (r = 0; r < 32; r += 4) {
mid = x[1] ^ x[2] ^ x[3] ^ roundKey[r + 0]
mid = byteSub(mid)
x[0] ^= l1(mid) // x4
mid = x[2] ^ x[3] ^ x[0] ^ roundKey[r + 1]
mid = byteSub(mid)
x[1] ^= l1(mid) // x5
mid = x[3] ^ x[0] ^ x[1] ^ roundKey[r + 2]
mid = byteSub(mid)
x[2] ^= l1(mid) // x6
mid = x[0] ^ x[1] ^ x[2] ^ roundKey[r + 3]
mid = byteSub(mid)
x[3] ^= l1(mid) // x7
}
// Reverse
for (let j = 0; j < 16; j += 4) {
output[j] = x[3 - j / 4] >>> 24 & 0xff
output[j + 1] = x[3 - j / 4] >>> 16 & 0xff
output[j + 2] = x[3 - j / 4] >>> 8 & 0xff
output[j + 3] = x[3 - j / 4] & 0xff
}
}
function sms4KeyExt(key, roundKey, cryptFlag) {
let r
let mid
const x = new Array(4)
const tmp = new Array(4)
for (let i = 0; i < 4; i++) {
tmp[0] = key[0 + 4 * i] & 0xff
tmp[1] = key[1 + 4 * i] & 0xff
tmp[2] = key[2 + 4 * i] & 0xff
tmp[3] = key[3 + 4 * i] & 0xff
x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3]
}
x[0] ^= 0xa3b1bac6
x[1] ^= 0x56aa3350
x[2] ^= 0x677d9197
x[3] ^= 0xb27022dc
for (r = 0; r < 32; r += 4) {
mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0]
mid = byteSub(mid)
roundKey[r + 0] = x[0] ^= l2(mid) // roundKey0 = K4
mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1]
mid = byteSub(mid)
roundKey[r + 1] = x[1] ^= l2(mid) // roundKey1 = K5
mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2]
mid = byteSub(mid)
roundKey[r + 2] = x[2] ^= l2(mid) // roundKey2 = K6
mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3]
mid = byteSub(mid)
roundKey[r + 3] = x[3] ^= l2(mid) // roundKey3 = K7
}
// 解密时轮密钥使用顺序:roundKey31, roundKey30, ..., roundKey0
if (cryptFlag === DECRYPT) {
for (r = 0; r < 16; r++) {
mid = roundKey[r]
roundKey[r] = roundKey[31 - r]
roundKey[31 - r] = mid
}
}
}
function sm4(inArray, key, cryptFlag) {
const outArray = []
let point = 0
const roundKey = new Array(ROUND)
sms4KeyExt(key, roundKey, cryptFlag)
let input = new Array(16)
const output = new Array(16)
let inLen = inArray.length
while (inLen >= BLOCK) {
input = inArray.slice(point, point + 16)
sms4Crypt(input, output, roundKey)
for (let i = 0; i < BLOCK; i++) {
outArray[point + i] = output[i]
}
inLen -= BLOCK
point += BLOCK
}
return outArray
}
module.exports = {
encrypt(inArray, key) {
return sm4(inArray, key, 1)
},
decrypt(inArray, key) {
return sm4(inArray, key, 0)
}
}
const sm2 = require('../src/index').sm2
const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3
// const msgString = 'abcdefghABCDEFGH12345678abcdefghABCDEFGH12345678abcdefghABCDabcdefghABCDEFGH12345678abcdefghABCDEFGH12345678abcdefghABCDabcdefghABCDEFGH12345678abcdefghABCDEFGH12345678abcdefghABCDabcdefghABCDEFGH12345678abcdefghABCDEFGH12345678abcdefghABCDabcdefghABCDEFGH';
const msgString = 'absasdagfadgadsfdfdsf'
let publicKey
let privateKey
beforeAll(() => {
// 生成密钥对
let keypair = sm2.generateKeyPairHex()
publicKey = keypair.publicKey
privateKey = keypair.privateKey
});
test('sm2: generate keypair', () => {
expect(publicKey.length).toBe(130)
expect(privateKey.length).toBe(64)
});
test('sm2: encrypt and decrypt data', () => {
let encryptData = sm2.doEncrypt(msgString, publicKey, cipherMode)
let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode)
expect(decryptData).toBe(msgString)
for (let i = 0; i < 100; i++) {
let encryptData = sm2.doEncrypt(msgString, publicKey, cipherMode)
let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode)
expect(decryptData).toBe(msgString)
}
})
test('sm2: sign data and verify sign', () => {
// 纯签名 + 生成椭圆曲线点
let sigValueHex = sm2.doSignature(msgString, privateKey)
let verifyResult = sm2.doVerifySignature(msgString, sigValueHex, publicKey)
expect(verifyResult).toBe(true)
// 纯签名
let sigValueHex2 = sm2.doSignature(msgString, privateKey, {
pointPool: [sm2.getPoint(), sm2.getPoint(), sm2.getPoint(), sm2.getPoint()],
})
let verifyResult2 = sm2.doVerifySignature(msgString, sigValueHex2, publicKey);
expect(verifyResult2).toBe(true)
// 纯签名 + 生成椭圆曲线点 + der编解码
let sigValueHex3 = sm2.doSignature(msgString, privateKey, {
der: true,
})
let verifyResult3 = sm2.doVerifySignature(msgString, sigValueHex3, publicKey, {
der: true,
})
expect(verifyResult3).toBe(true)
// 纯签名 + 生成椭圆曲线点 + sm3杂凑
let sigValueHex4 = sm2.doSignature(msgString, privateKey, {
hash: true,
})
let verifyResult4 = sm2.doVerifySignature(msgString, sigValueHex4, publicKey, {
hash: true,
})
expect(verifyResult4).toBe(true)
for (let i = 0; i < 100; i++) {
sigValueHex4 = sm2.doSignature(msgString, privateKey, {
hash: true,
})
verifyResult4 = sm2.doVerifySignature(msgString, sigValueHex4, publicKey, {
hash: true,
})
expect(verifyResult4).toBe(true)
}
// 纯签名 + 生成椭圆曲线点 + sm3杂凑(不做公钥推导)
let sigValueHex5 = sm2.doSignature(msgString, privateKey, {
hash: true,
publicKey,
})
let verifyResult5 = sm2.doVerifySignature(msgString, sigValueHex5, publicKey, {
hash: true,
publicKey,
})
expect(verifyResult5).toBe(true)
})
const sm3 = require('../src/index').sm3
test('sm3: must match the result', () => {
expect(sm3('abc')).toBe('66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0')
expect(sm3('abcdefghABCDEFGH12345678')).toBe('d670c7f027fd5f9f0c163f4bfe98f9003fe597d3f52dbab0885ec2ca8dd23e9b')
expect(sm3('abcdefghABCDEFGH12345678abcdefghABCDEFGH12345678abcdefgh')).toBe('1cf3bafec325d7d9102cd67ba46b09195af4e613b6c2b898122363d810308b11')
expect(sm3('abcdefghABCDEFGH12345678abcdefghABCDEFGH12345678abcdefghABCD')).toBe('b8ac4203969bde27434ce667b0adbf3439ee97e416e73cb96f4431f478a531fe')
expect(sm3('abcdefghABCDEFGH12345678abcdefghABCDEFGH12345678abcdefghABCDEFGH')).toBe('5ef0cdbe0d54426eea7f5c8b44385bb1003548735feaa59137c3dfe608aa9567')
expect(sm3('abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd')).toBe('debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732')
})
const sm4 = require('../src/index').sm4
const key = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10]
test('sm4: encrypt a group', () => {
expect(sm4.encrypt([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10], key)).toEqual([0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46])
})
test('sm4: decrypt a group', () => {
expect(sm4.decrypt([0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46], key)).toEqual([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10])
})
test('sm4: encrypt several groups', () => {
expect(sm4.encrypt([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10], key)).toEqual([0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46, 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46])
})
test('sm4: decrypt several groups', () => {
expect(sm4.decrypt([0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46, 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46], key)).toEqual([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10])
})
test('sm4: encrypt a group whit 1000000 times', () => {
let temp = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10]
for (let i = 0; i < 1000000; i++) {
temp = sm4.encrypt(temp, key)
}
expect(temp).toEqual([0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d, 0x3f, 0x66])
})
const SM = require('./src')
function getKeys(secret) {
// const hash = createHash(Buffer.from(secret))
// const m = new Uint8Array(nacl.sign.seedLength)
// for (let i = 0; i < m.length; i++) m[i] = hash[i]
// const keypair = nacl.sign.keyPair.fromSeed(m)
/**
* {
publicKey: '0x10d15cb4a3747d9bcf6339ef7b1d8462e86da595e7da3f4dd17bb1b7e3b43cf9c67e41a439ec1ddae15e697b71bbfa2c4f662fce5105fc21c404df9ddae513f7',
privateKey: '5c3e9a13ff5618cca46bdf5780c4391e89af27eeea044c90ad9684f4fb51c453'
}
*/
const hash=SM.sm3(secret)
const keypair =SM.sm2.generateKeyPairHex(hash)
let sigValueHex = SM.sm2.doSignature(secret, keypair.privateKey)
let verifyResult = SM.sm2.doVerifySignature(secret, sigValueHex, keypair.publicKey)
console.log(verifyResult)
return {
publicKey: (keypair.publicKey),
privateKey: (keypair.privateKey)
}
}
function bufToHex(data) {
return Buffer.from(data).toString('hex')
}
console.log(getKeys("enter boring shaft rent essence foil trick vibrant fabric quote indoor output sdfdg deessa"))
console.log(Buffer.from('045e135d451a0dfbb3d01a3357ecae989aced67afe51ff28f6f6a16fc1a67488c47ee1eb00cb70b217f51ae9e1b96141115fca564a1694fe7390474f4c1bd59a51').length)
\ No newline at end of file
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: {
sm2: './src/sm2/index.js',
sm3: './src/sm3/index.js',
sm4: './src/sm4/index.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
library: '[name]',
libraryTarget: 'window',
},
module: {
loaders: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}]
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
]
};