Commit 75a6786c by cf

added ASN1 and GM

parent aedfe2fb
...@@ -4,7 +4,7 @@ about: Create a report to help us improve ...@@ -4,7 +4,7 @@ about: Create a report to help us improve
--- ---
**Version of ZSWJS** **Version of zswjs**
_which version of zswjs exhibits the issue_ _which version of zswjs exhibits the issue_
**Describe the bug** **Describe the bug**
......
# Contributing to ZSWJS # Contributing to zswjs
Interested in contributing? That's awesome! Here are some guidelines to get started quickly and easily: Interested in contributing? That's awesome! Here are some guidelines to get started quickly and easily:
...@@ -6,7 +6,7 @@ Interested in contributing? That's awesome! Here are some guidelines to get star ...@@ -6,7 +6,7 @@ Interested in contributing? That's awesome! Here are some guidelines to get star
- [Bug Reports](#bug-reports) - [Bug Reports](#bug-reports)
- [Feature Requests](#feature-requests) - [Feature Requests](#feature-requests)
- [Change Requests](#change-requests) - [Change Requests](#change-requests)
- [Working on ZSWJS](#working-on-zswjs) - [Working on zswjs](#working-on-zswjs)
- [Feature Branches](#feature-branches) - [Feature Branches](#feature-branches)
- [Submitting Pull Requests](#submitting-pull-requests) - [Submitting Pull Requests](#submitting-pull-requests)
- [Testing](#testing) - [Testing](#testing)
...@@ -17,7 +17,7 @@ Interested in contributing? That's awesome! Here are some guidelines to get star ...@@ -17,7 +17,7 @@ Interested in contributing? That's awesome! Here are some guidelines to get star
## Reporting An Issue ## Reporting An Issue
If you're about to raise an issue because you think you've found a problem with ZSWJS, or you'd like to make a request for a new feature in the codebase, or any other reason… please read this first. If you're about to raise an issue because you think you've found a problem with zswjs, or you'd like to make a request for a new feature in the codebase, or any other reason… please read this first.
The GitHub issue tracker is the preferred channel for [bug reports](#bug-reports), [feature requests](#feature-requests), and [submitting pull requests](#submitting-pull-requests), but please respect the following restrictions: The GitHub issue tracker is the preferred channel for [bug reports](#bug-reports), [feature requests](#feature-requests), and [submitting pull requests](#submitting-pull-requests), but please respect the following restrictions:
...@@ -52,13 +52,13 @@ Feature requests are welcome. Before you submit one be sure to have: ...@@ -52,13 +52,13 @@ Feature requests are welcome. Before you submit one be sure to have:
### Change Requests ### Change Requests
Change requests cover both architectural and functional changes to how ZSWJS works. If you have an idea for a new or different dependency, a refactor, or an improvement to a feature, etc - please be sure to: Change requests cover both architectural and functional changes to how zswjs works. If you have an idea for a new or different dependency, a refactor, or an improvement to a feature, etc - please be sure to:
1. **Use the GitHub search** and check someone else didn't get there first 1. **Use the GitHub search** and check someone else didn't get there first
1. Take a moment to think about the best way to make a case for, and explain what you're thinking. Are you sure this shouldn't really be 1. Take a moment to think about the best way to make a case for, and explain what you're thinking. Are you sure this shouldn't really be
a [bug report](#bug-reports) or a [feature request](#feature-requests)? Is it really one idea or is it many? What's the context? What problem are you solving? Why is what you are suggesting better than what's already there? a [bug report](#bug-reports) or a [feature request](#feature-requests)? Is it really one idea or is it many? What's the context? What problem are you solving? Why is what you are suggesting better than what's already there?
## Working on ZSWJS ## Working on zswjs
Code contributions are welcome and encouraged! If you are looking for a good place to start, check out the [good first issue](https://github.com/zhongshuwen/zswjs/labels/good%20first%20issue) label in GitHub issues. Code contributions are welcome and encouraged! If you are looking for a good place to start, check out the [good first issue](https://github.com/zhongshuwen/zswjs/labels/good%20first%20issue) label in GitHub issues.
...@@ -69,7 +69,7 @@ Also, please follow these guidelines when submitting code: ...@@ -69,7 +69,7 @@ Also, please follow these guidelines when submitting code:
To get it out of the way: To get it out of the way:
- **[develop](https://github.com/zhongshuwen/zswjs/tree/develop)** is the development branch. All work on the next release happens here so you should generally branch off `develop`. Do **NOT** use this branch for a production site. - **[develop](https://github.com/zhongshuwen/zswjs/tree/develop)** is the development branch. All work on the next release happens here so you should generally branch off `develop`. Do **NOT** use this branch for a production site.
- **[master](https://github.com/zhongshuwen/zswjs/tree/master)** contains the latest release of ZSWJS. This branch may be used in production. Do **NOT** use this branch to work on ZSWJS's source. - **[master](https://github.com/zhongshuwen/zswjs/tree/master)** contains the latest release of zswjs. This branch may be used in production. Do **NOT** use this branch to work on zswjs's source.
### Submitting Pull Requests ### Submitting Pull Requests
...@@ -77,11 +77,11 @@ Pull requests are awesome. If you're looking to raise a PR for something which d ...@@ -77,11 +77,11 @@ Pull requests are awesome. If you're looking to raise a PR for something which d
### Testing ### Testing
ZSWJS is used by many libraries across the 中数文联盟链 ecosystem, so proper testing is absolutely essential prior to opening a pull request. This can be done in ZSWJS by running `yarn build-production`. This command will build the distrubution bundles (`yarn build-all`) and test each environment accordingly (`yarn test-all`). zswjs is used by many libraries across the 中数文联盟链 ecosystem, so proper testing is absolutely essential prior to opening a pull request. This can be done in zswjs by running `yarn build-production`. This command will build the distrubution bundles (`yarn build-all`) and test each environment accordingly (`yarn test-all`).
#### Automated Unit Test Suite #### Automated Unit Test Suite
`yarn test` will run through the core functionality of each ZSWJS module with Jest. `yarn test` will run through the core functionality of each zswjs module with Jest.
#### Integration Test Suite #### Integration Test Suite
......
{ {
"name": "zswjs", "name": "zswjs",
"version": "1.0.0", "version": "1.2.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
...@@ -995,6 +995,12 @@ ...@@ -995,6 +995,12 @@
"pretty-format": "^26.0.0" "pretty-format": "^26.0.0"
} }
}, },
"@types/jsbn": {
"version": "1.2.30",
"resolved": "https://registry.npmjs.org/@types/jsbn/-/jsbn-1.2.30.tgz",
"integrity": "sha512-VZouplBofjq3YOIHLNRBDxILs/nAArdTZ2QP1ooflyhS+yPExWsFE+i2paBIBb7OI3NJShfcde/nogqk4SPB/Q==",
"dev": true
},
"@types/json-schema": { "@types/json-schema": {
"version": "7.0.9", "version": "7.0.9",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
...@@ -2651,6 +2657,14 @@ ...@@ -2651,6 +2657,14 @@
"requires": { "requires": {
"jsbn": "~0.1.0", "jsbn": "~0.1.0",
"safer-buffer": "^2.1.0" "safer-buffer": "^2.1.0"
},
"dependencies": {
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"dev": true
}
} }
}, },
"ecurve": { "ecurve": {
...@@ -4965,10 +4979,9 @@ ...@@ -4965,10 +4979,9 @@
} }
}, },
"jsbn": { "jsbn": {
"version": "0.1.1", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "integrity": "sha1-sBMHyym2GKHtJux56RH4A8TaAEA="
"dev": true
}, },
"jsdom": { "jsdom": {
"version": "16.7.0", "version": "16.7.0",
...@@ -6841,6 +6854,14 @@ ...@@ -6841,6 +6854,14 @@
"jsbn": "~0.1.0", "jsbn": "~0.1.0",
"safer-buffer": "^2.0.2", "safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0" "tweetnacl": "~0.14.0"
},
"dependencies": {
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"dev": true
}
} }
}, },
"stack-utils": { "stack-utils": {
......
...@@ -30,12 +30,14 @@ ...@@ -30,12 +30,14 @@
"bn.js": "5.2.0", "bn.js": "5.2.0",
"elliptic": "6.5.4", "elliptic": "6.5.4",
"hash.js": "1.1.7", "hash.js": "1.1.7",
"jsbn": "^1.1.0",
"pako": "2.0.3" "pako": "2.0.3"
}, },
"devDependencies": { "devDependencies": {
"@cypress/skip-test": "^2.6.1", "@cypress/skip-test": "^2.6.1",
"@types/elliptic": "^6.4.13", "@types/elliptic": "^6.4.13",
"@types/jest": "^26.0.24", "@types/jest": "^26.0.24",
"@types/jsbn": "^1.2.30",
"@types/node": "^14.17.5", "@types/node": "^14.17.5",
"@types/node-fetch": "^2.5.11", "@types/node-fetch": "^2.5.11",
"@types/pako": "^1.0.2", "@types/pako": "^1.0.2",
......
/* eslint-disable class-methods-use-this */
import { BigInteger } from 'jsbn';
function bigintToValue(bigint: BigInteger) {
let h: any = bigint.toString(16)
if (h[0] !== '-') {
// 正数
if (h.length % 2 === 1) h = '0' + h // 补齐到整字节
else if (!h.match(/^[0-7]/)) h = '00' + h // 非0开头,则补一个全0字节
} else {
// 负数
h = h.substr(1)
let len = h.length
if (len % 2 === 1) len += 1 // 补齐到整字节
else if (!h.match(/^[0-7]/)) len += 2 // 非0开头,则补一个全0字节
let mask: any = ''
for (let i = 0; i < len; i++) mask += 'f'
mask = new BigInteger(mask, 16)
// 对绝对值取反,加1
h = mask.xor(bigint).add(BigInteger.ONE)
h = h.toString(16).replace(/^-/, '')
}
return h
}
class ASN1Object {
tlv: any;
t: string;
l: string;
v: string;
constructor() {
this.tlv = null
this.t = '00'
this.l = '00'
this.v = ''
}
/**
* 获取 der 编码比特流16进制串
*/
getEncodedHex() {
if (!this.tlv) {
this.v = this.getValue()
this.l = this.getLength()
this.tlv = this.t + this.l + this.v
}
return this.tlv
}
getLength() {
const n = this.v.length / 2 // 字节数
let nHex = n.toString(16)
if (nHex.length % 2 === 1) nHex = '0' + nHex // 补齐到整字节
if (n < 128) {
// 短格式,以 0 开头
return nHex
} else {
// 长格式,以 1 开头
const head = 128 + nHex.length / 2 // 1(1位) + 真正的长度占用字节数(7位) + 真正的长度
return head.toString(16) + nHex
}
}
getValue() {
return ''
}
}
class DERInteger extends ASN1Object {
t: string;
constructor(bigint: any) {
super()
this.t = '02' // 整型标签说明
if (bigint) this.v = bigintToValue(bigint)
}
getValue() {
return this.v
}
}
class DERSequence extends ASN1Object {
t: string;
asn1Array: any[];
constructor(asn1Array: any[]) {
super()
this.t = '30' // 序列标签说明
this.asn1Array = asn1Array
}
getValue() {
this.v = this.asn1Array.map(asn1Object => asn1Object.getEncodedHex()).join('')
return this.v
}
}
/**
* 获取 l 占用字节数
*/
function getLenOfL(str: string, start: number) {
if (+str[start + 2] < 8) return 1 // l 以0开头,则表示短格式,只占一个字节
return +str.substr(start + 2, 2) & 0x7f + 1 // 长格式,取第一个字节后7位作为长度真正占用字节数,再加上本身
}
/**
* 获取 l
*/
function getL(str: string, start: number) {
// 获取 l
const len = getLenOfL(str, start)
const l = str.substr(start + 2, len * 2)
if (!l) return -1
const bigint = +l[0] < 8 ? new BigInteger(l, 16) : new BigInteger(l.substr(2), 16)
return bigint.intValue()
}
/**
* 获取 v 的位置
*/
function getStartOfV(str: string, start: number) {
const len = getLenOfL(str, start)
return start + (len + 1) * 2
}
/**
* ASN.1 der 编码,针对 sm2 签名
*/
export function encodeDer(r: BigInteger, s: BigInteger): string {
const derR = new DERInteger(r)
const derS = new DERInteger(s)
const derSeq = new DERSequence([derR, derS])
return derSeq.getEncodedHex()
}
/**
* 解析 ASN.1 der,针对 sm2 验签
*/
export function decodeDer(input: string) {
// 结构:
// input = | tSeq | lSeq | vSeq |
// vSeq = | tR | lR | vR | tS | lS | vS |
const start = getStartOfV(input, 0)
const vIndexR = getStartOfV(input, start)
const lR = getL(input, start)
const vR = input.substr(vIndexR, lR * 2)
const nextStart = vIndexR + vR.length
const vIndexS = getStartOfV(input, nextStart)
const lS = getL(input, nextStart)
const vS = input.substr(vIndexS, lS * 2)
const r = new BigInteger(vR, 16)
const s = new BigInteger(vS, 16)
return { r, s }
}
...@@ -73,13 +73,15 @@ export class PrivateKey { ...@@ -73,13 +73,15 @@ export class PrivateKey {
const constructSignature = (options: EC.SignOptions): Signature => { const constructSignature = (options: EC.SignOptions): Signature => {
const ellipticPrivateKey = this.toElliptic(); const ellipticPrivateKey = this.toElliptic();
const ellipticSignature = ellipticPrivateKey.sign(data, options); const ellipticSignature = ellipticPrivateKey.sign(data, options);
return Signature.fromElliptic(ellipticSignature, this.getType(), this.ec); return Signature.fromElliptic(ellipticSignature, this.getType(), this.ec, this.getPublicKey());
}; };
if (this.key.type === KeyType.k1) { if (this.key.type === KeyType.k1) {
do { do {
signature = constructSignature({canonical: true, pers: [++tries]}); signature = constructSignature({canonical: true, pers: [++tries]});
} while (!isCanonical(signature.toBinary())); } while (!isCanonical(signature.toBinary()));
} else if (this.key.type === KeyType.gm) {
signature = constructSignature({canonical: true});
} else { } else {
signature = constructSignature({canonical: true}); signature = constructSignature({canonical: true});
} }
......
...@@ -38,6 +38,10 @@ export class PublicKey { ...@@ -38,6 +38,10 @@ export class PublicKey {
public toString(): string { public toString(): string {
return publicKeyToString(this.key); return publicKeyToString(this.key);
} }
/** Export public key as 中数文联盟链-format uint8array */
public getData(){
return this.key.data;
}
/** Export public key as Legacy 中数文联盟链-format public key */ /** Export public key as Legacy 中数文联盟链-format public key */
public toLegacyString(): string { public toLegacyString(): string {
......
import { BNInput, ec as EC } from 'elliptic'; import { BNInput, ec as EC } from 'elliptic';
import BN = require('bn.js'); import {BigInteger} from 'jsbn';
import {BN} from 'bn.js'
import { import {
Key, Key,
...@@ -8,6 +9,8 @@ import { ...@@ -8,6 +9,8 @@ import {
stringToSignature, stringToSignature,
} from './zswjs-numeric'; } from './zswjs-numeric';
import { constructElliptic, PublicKey } from './zswjs-key-conversions'; import { constructElliptic, PublicKey } from './zswjs-key-conversions';
import { encodeDer } from './ASN1';
import { arrayToHex, hexToUint8Array } from './zswjs-serialize';
/** Represents/stores a Signature and provides easy conversion for use with `elliptic` lib */ /** Represents/stores a Signature and provides easy conversion for use with `elliptic` lib */
export class Signature { export class Signature {
...@@ -23,9 +26,31 @@ export class Signature { ...@@ -23,9 +26,31 @@ export class Signature {
} }
/** Instantiate Signature from an `elliptic`-format Signature */ /** Instantiate Signature from an `elliptic`-format Signature */
public static fromElliptic(ellipticSig: EC.Signature, keyType: KeyType, ec?: EC): Signature { public static fromElliptic(ellipticSig: EC.Signature, keyType: KeyType, ec?: EC, pubKey?: PublicKey): Signature {
const r = ellipticSig.r.toArray('be', 32); const r = ellipticSig.r.toArray('be', 32);
const s = ellipticSig.s.toArray('be', 32); const s = ellipticSig.s.toArray('be', 32);
if(keyType===KeyType.gm){
if(!pubKey){
throw new Error("fromElliptic requires pub key for gm type!")
}
if (!ec) {
ec = constructElliptic(keyType);
}
const pubDataHex =arrayToHex(pubKey.getData());
const rStr = ellipticSig.r.toString();
const sStr = ellipticSig.s.toString();
const encDerPubData1 = encodeDer(
new BigInteger(rStr),
new BigInteger(sStr),
);
const allData = (pubDataHex+encDerPubData1+"000000000000000000000000000000000000000000000000").substring(0,105*2);
return new Signature({
type: keyType,
data: hexToUint8Array(allData),
}, ec);
}
let zswchainRecoveryParam; let zswchainRecoveryParam;
if (keyType === KeyType.k1 || keyType === KeyType.r1) { if (keyType === KeyType.k1 || keyType === KeyType.r1) {
zswchainRecoveryParam = ellipticSig.recoveryParam + 27; zswchainRecoveryParam = ellipticSig.recoveryParam + 27;
......
import {ec as EC} from 'elliptic'; import {ec as EC, curves} from 'elliptic';
import * as hash from 'hash.js'; import * as hash from 'hash.js';
import {KeyType} from './zswjs-numeric'; import {KeyType} from './zswjs-numeric';
import { PublicKey } from './PublicKey'; import { PublicKey } from './PublicKey';
...@@ -8,10 +8,31 @@ export { PrivateKey } from './PrivateKey'; ...@@ -8,10 +8,31 @@ export { PrivateKey } from './PrivateKey';
export { PublicKey } from './PublicKey'; export { PublicKey } from './PublicKey';
export { Signature } from './Signature'; export { Signature } from './Signature';
const SM2_PARAMS : curves.PresetCurve.Options= {
type: 'SM2',
prime: null,
p: 'FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF',
a: 'FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC',
b: '28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93',
n: 'FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123',
hash: hash.sha256,
gRed: false,
g: [
'32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7',
'BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0'
]
}
/** Construct the elliptic curve object based on key type */ /** Construct the elliptic curve object based on key type */
export const constructElliptic = (type: KeyType): EC => { export const constructElliptic = (type: KeyType): EC => {
if (type === KeyType.k1) { if (type === KeyType.k1) {
return new EC('secp256k1'); return new EC('secp256k1');
}else if(type === KeyType.gm){
return new EC(new curves.PresetCurve(SM2_PARAMS));
} }
return new EC('p256'); return new EC('p256');
}; };
...@@ -25,12 +46,7 @@ export const generateKeyPair = ( ...@@ -25,12 +46,7 @@ export const generateKeyPair = (
'options to `true`. If this does describe your environment and you set `secureEnv` to `true`, ' + 'options to `true`. If this does describe your environment and you set `secureEnv` to `true`, ' +
'YOU DO SO AT YOUR OWN RISK AND THE RISK OF YOUR USERS.'); 'YOU DO SO AT YOUR OWN RISK AND THE RISK OF YOUR USERS.');
} }
let ec; let ec = constructElliptic(type);
if (type === KeyType.k1) {
ec = new EC('secp256k1');
} else {
ec = new EC('p256');
}
const ellipticKeyPair = ec.genKeyPair(options.ecOptions); const ellipticKeyPair = ec.genKeyPair(options.ecOptions);
const publicKey = PublicKey.fromElliptic(ellipticKeyPair, type, ec); const publicKey = PublicKey.fromElliptic(ellipticKeyPair, type, ec);
const privateKey = PrivateKey.fromElliptic(ellipticKeyPair, type, ec); const privateKey = PrivateKey.fromElliptic(ellipticKeyPair, type, ec);
......
...@@ -256,6 +256,7 @@ export enum KeyType { ...@@ -256,6 +256,7 @@ export enum KeyType {
k1 = 0, k1 = 0,
r1 = 1, r1 = 1,
wa = 2, wa = 2,
gm = 4,
} }
/** Public key data size, excluding type field */ /** Public key data size, excluding type field */
...@@ -354,6 +355,8 @@ export const publicKeyToString = (key: Key): string => { ...@@ -354,6 +355,8 @@ export const publicKeyToString = (key: Key): string => {
return keyToString(key, 'R1', 'PUB_R1_'); return keyToString(key, 'R1', 'PUB_R1_');
} else if (key.type === KeyType.wa) { } else if (key.type === KeyType.wa) {
return keyToString(key, 'WA', 'PUB_WA_'); return keyToString(key, 'WA', 'PUB_WA_');
} else if (key.type === KeyType.gm) {
return keyToString(key, 'GM', 'PUB_GM_');
} else { } else {
throw new Error('unrecognized public key format'); throw new Error('unrecognized public key format');
} }
...@@ -385,6 +388,8 @@ export const stringToPrivateKey = (s: string): Key => { ...@@ -385,6 +388,8 @@ export const stringToPrivateKey = (s: string): Key => {
return stringToKey(s.substr(7), KeyType.r1, privateKeyDataSize, 'R1'); return stringToKey(s.substr(7), KeyType.r1, privateKeyDataSize, 'R1');
} else if (s.substr(0, 7) === 'PVT_K1_') { } else if (s.substr(0, 7) === 'PVT_K1_') {
return stringToKey(s.substr(7), KeyType.k1, privateKeyDataSize, 'K1'); return stringToKey(s.substr(7), KeyType.k1, privateKeyDataSize, 'K1');
} else if (s.substr(0, 7) === 'PVT_GM_') {
return stringToKey(s.substr(7), KeyType.gm, privateKeyDataSize, 'GM');
} else { } else {
// todo: Verify checksum: sha256(sha256(key.data)). // todo: Verify checksum: sha256(sha256(key.data)).
// Not critical since a bad key will fail to produce a // Not critical since a bad key will fail to produce a
...@@ -434,6 +439,8 @@ export const privateKeyToString = (key: Key): string => { ...@@ -434,6 +439,8 @@ export const privateKeyToString = (key: Key): string => {
return keyToString(key, 'R1', 'PVT_R1_'); return keyToString(key, 'R1', 'PVT_R1_');
} else if (key.type === KeyType.k1) { } else if (key.type === KeyType.k1) {
return keyToString(key, 'K1', 'PVT_K1_'); return keyToString(key, 'K1', 'PVT_K1_');
} else if (key.type === KeyType.gm) {
return keyToString(key, 'GM', 'PVT_GM_');
} else { } else {
throw new Error('unrecognized private key format'); throw new Error('unrecognized private key format');
} }
...@@ -450,6 +457,8 @@ export const stringToSignature = (s: string): Key => { ...@@ -450,6 +457,8 @@ export const stringToSignature = (s: string): Key => {
return stringToKey(s.substr(7), KeyType.r1, signatureDataSize, 'R1'); return stringToKey(s.substr(7), KeyType.r1, signatureDataSize, 'R1');
} else if (s.substr(0, 7) === 'SIG_WA_') { } else if (s.substr(0, 7) === 'SIG_WA_') {
return stringToKey(s.substr(7), KeyType.wa, 0, 'WA'); return stringToKey(s.substr(7), KeyType.wa, 0, 'WA');
} else if (s.substr(0, 7) === 'SIG_GM_') {
return stringToKey(s.substr(7), KeyType.gm, 105, 'GM');
} else { } else {
throw new Error('unrecognized signature format'); throw new Error('unrecognized signature format');
} }
...@@ -463,6 +472,8 @@ export const signatureToString = (signature: Key): string => { ...@@ -463,6 +472,8 @@ export const signatureToString = (signature: Key): string => {
return keyToString(signature, 'R1', 'SIG_R1_'); return keyToString(signature, 'R1', 'SIG_R1_');
} else if (signature.type === KeyType.wa) { } else if (signature.type === KeyType.wa) {
return keyToString(signature, 'WA', 'SIG_WA_'); return keyToString(signature, 'WA', 'SIG_WA_');
} else if (signature.type === KeyType.gm) {
return keyToString(signature, 'GM', 'SIG_GM_');
} else { } else {
throw new Error('unrecognized signature format'); throw new Error('unrecognized signature format');
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment