@zlattice/lattice-js
Version:
Lattice blockchain TypeScript SDK with dual module support (CJS + ESM)
86 lines • 3.73 kB
JavaScript
import { ADDRESS_BYTES_LENGTH, ADDRESS_TITLE, ADDRESS_VERSION } from "../common/constants.js";
import { log } from "../logger.js";
import { Base58Impl } from "../utils/base58.js";
import { stripHexPrefix } from "../utils/string.js";
import { isHexString } from "@ethersproject/bytes";
import { secp256k1 } from "@noble/curves/secp256k1";
import { sha256 } from "@noble/hashes/sha2";
import { bytesToHex, randomBytes } from "@noble/hashes/utils";
export class NIST {
generateKeyPair() {
// Generate a random private key
let privateKey;
do {
privateKey = randomBytes(32);
} while (!secp256k1.utils.isValidPrivateKey(privateKey));
// Get the corresponding public key
const isCompressed = false;
const uncompressedPublicKey = secp256k1.getPublicKey(privateKey, isCompressed);
return {
privateKey: Buffer.from(privateKey),
publicKey: Buffer.from(uncompressedPublicKey)
};
}
compressPublicKey(publicKey) {
let publicKeyBuffer;
if (typeof publicKey === "string") {
publicKeyBuffer = Buffer.from(publicKey, "hex");
}
else {
publicKeyBuffer = publicKey;
}
if (publicKeyBuffer.length !== 65) {
log.error("Invalid public key length, expected size is 65, but actual size is %d", publicKeyBuffer.length);
throw new Error(`Invalid public key length, expected size is 65, but actual size is ${publicKeyBuffer.length}`);
}
// calculate x coordinate and y coordinate
const x = publicKeyBuffer.subarray(1, 33);
const y = BigInt(`0x${publicKeyBuffer.subarray(33, 65).toString("hex")}`);
// judge whether the y coordinate is even
// `02` represents even, `03` represents odd.
let prefix = "02";
if (y % BigInt(2) === BigInt(1)) {
prefix = "03";
}
return Buffer.from(`${prefix}${x.toString("hex")}`, "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}`);
}
const publicKey = secp256k1.getPublicKey(stripHexPrefix(privateKey), compressed);
return `0x${bytesToHex(publicKey)}`;
}
hash(data) {
return Buffer.from(sha256(data));
}
encodeHash(encodeFunc) {
const hash = encodeFunc();
return this.hash(hash);
}
sign(data, privateKey) {
const signature = secp256k1.sign(data, stripHexPrefix(privateKey));
return `0x${signature.toCompactHex()}`;
}
verify(data, signature, uncompressedPublicKey) {
const recoveredSignature = secp256k1.Signature.fromCompact(stripHexPrefix(signature));
return secp256k1.verify(recoveredSignature, data, stripHexPrefix(uncompressedPublicKey));
}
}
//# sourceMappingURL=crypto-secp256k1.js.map