UNPKG

@zlattice/lattice-js

Version:

Lattice blockchain TypeScript SDK with dual module support (CJS + ESM)

101 lines 4.71 kB
import { ADDRESS_BYTES_LENGTH, ADDRESS_TITLE, HEX_PREFIX, SM2P256V1_SIGNATURE_LENGTH, SM2P256V1_SIGNATURE_REMARK } from "../common/constants.js"; import { ADDRESS_VERSION } from "../common/constants.js"; import { compressPublicKeyHex, doSignature, doVerifySignature, generateKeyPairHex, getHash, getPublicKeyFromPrivateKey } from "../crypto/sm2/index.js"; import sm3 from "../crypto/sm3/index.js"; import { log } from "../logger.js"; import { Base58Impl } from "../utils/base58.js"; import { stripHexPrefix } from "../utils/index.js"; import { isHexString } from "@ethersproject/bytes"; export class GM { generateKeyPair() { const { privateKey, publicKey: uncompressedPublicKey } = generateKeyPairHex(); return { privateKey: Buffer.from(privateKey, "hex"), publicKey: Buffer.from(uncompressedPublicKey, "hex") }; } compressPublicKey(publicKey) { let publicKeyBuffer; if (typeof publicKey === "string") { publicKeyBuffer = Buffer.from(publicKey, "hex"); } else { publicKeyBuffer = publicKey; } if (publicKeyBuffer.length !== 65) { log.error("Invalid uncompressed public key length, expected size is 65, but actual size is %d", publicKeyBuffer.length); throw new Error(`Invalid uncompressed public key length, expected size is 65, but actual size is ${publicKeyBuffer.length}`); } const compressedPublicKey = compressPublicKeyHex(publicKey.toString("hex")); return Buffer.from(compressedPublicKey, "hex"); } publicKeyToAddress(publicKey) { let publicKeyBuffer; if (typeof publicKey === "string") { publicKeyBuffer = Buffer.from(stripHexPrefix(publicKey), "hex"); } else { publicKeyBuffer = publicKey; } if (publicKeyBuffer.length < 64) { throw new Error(`Invalid public key length, expected size greater than or equal to 64, but actual size is ${publicKeyBuffer.length}`); } const bs = this.hash(publicKeyBuffer.subarray(publicKeyBuffer.length - 64)); const base58 = new Base58Impl(); const address = base58.checkEncode(bs.subarray(bs.length - ADDRESS_BYTES_LENGTH), ADDRESS_VERSION); return `${ADDRESS_TITLE}_${address}`; } getPublicKeyFromPrivateKey(privateKey, compressed = false) { if (!isHexString(privateKey)) { throw new Error(`Invalid private key, excepted hex string, but actual is ${privateKey}`); } return getPublicKeyFromPrivateKey(privateKey.startsWith(HEX_PREFIX) ? privateKey.slice(HEX_PREFIX.length) : privateKey, compressed); } hash(data) { const hash = sm3(data); // 杂凑 return Buffer.from(hash, "hex"); } encodeHash(encodeFunc) { const hash = encodeFunc(); return this.hash(hash); } sign(data, privateKey) { const buffer = Buffer.from(privateKey, "hex"); if (buffer.length !== 32) { throw new Error(`Invalid private key length, expected size is 32, but actual size is ${buffer.length}`); } const signature = doSignature(data, privateKey, { hash: true }); const signatureBuffer = Buffer.alloc(SM2P256V1_SIGNATURE_LENGTH); signatureBuffer.write(signature, 0, 64, "hex"); // r、s signatureBuffer.write(SM2P256V1_SIGNATURE_REMARK, 64, 1, "hex"); // remark // calculate e point const publicKey = getPublicKeyFromPrivateKey(privateKey); const hashHex = getHash(data, publicKey); signatureBuffer.write(hashHex, 65, 32, "hex"); if (signatureBuffer.length !== SM2P256V1_SIGNATURE_LENGTH) { throw new Error(`Invalid signature length, expected size is ${SM2P256V1_SIGNATURE_LENGTH}, but actual size is ${signatureBuffer.length}`); } return signatureBuffer.toString("hex"); } verify(data, signature, uncompressedPublicKey) { const buffer = Buffer.from(uncompressedPublicKey, "hex"); if (buffer.length !== 65) { throw new Error(`Invalid uncompressed public key length, expected size is 65, but actual size is ${buffer.length}`); } let tempSignature = signature; if (signature.startsWith(HEX_PREFIX)) { tempSignature = signature.slice(HEX_PREFIX.length); } if (tempSignature.length > 128) { tempSignature = tempSignature.slice(0, 128); } return doVerifySignature(data, tempSignature, uncompressedPublicKey, { hash: true }); } } //# sourceMappingURL=crypto-sm2p256v1.js.map