@zlattice/lattice-js
Version:
Lattice blockchain TypeScript SDK with dual module support (CJS + ESM)
101 lines • 4.71 kB
JavaScript
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