@zlattice/lattice-js
Version:
Lattice blockchain TypeScript SDK with dual module support (CJS + ESM)
69 lines • 2.72 kB
JavaScript
import * as utils from '@noble/curves/abstract/utils';
import { EmptyArray, getZ } from './index.js';
import { field, sm2Curve } from './ec.js';
import { sm3 } from './sm3.js';
import { hexToArray, leftPad } from './utils.js';
// 用到的常数
const wPow2 = utils.hexToNumber('80000000000000000000000000000000');
const wPow2Sub1 = utils.hexToNumber('7fffffffffffffffffffffffffffffff');
// from sm2 sign part, extracted for code reusable.
function hkdf(z, keylen) {
const msg = new Uint8Array(keylen);
let ct = 1;
let offset = 0;
let t = EmptyArray;
const ctShift = new Uint8Array(4);
const nextT = () => {
// (1) Hai = hash(z || ct)
// (2) ct++
ctShift[0] = ct >> 24 & 0x00ff;
ctShift[1] = ct >> 16 & 0x00ff;
ctShift[2] = ct >> 8 & 0x00ff;
ctShift[3] = ct & 0x00ff;
//t = sm3(utils.concatBytes(z, ctShift))
t = sm3(utils.concatBytes(z, ctShift));
ct++;
offset = 0;
};
nextT(); // 先生成 Ha1
for (let i = 0, len = msg.length; i < len; i++) {
// t = Ha1 || Ha2 || Ha3 || Ha4
if (offset === t.length)
nextT();
// 输出 stream
msg[i] = t[offset++] & 0xff;
}
return msg;
}
export function calculateSharedKey(keypairA, ephemeralKeypairA, publicKeyB, ephemeralPublicKeyB, sharedKeyLength, isRecipient = false, idA = '1234567812345678', idB = '1234567812345678') {
const RA = sm2Curve.ProjectivePoint.fromHex(ephemeralKeypairA.publicKey);
const RB = sm2Curve.ProjectivePoint.fromHex(ephemeralPublicKeyB);
// const PA = sm2Curve.ProjectivePoint.fromHex(keypairA.publicKey) // 用不到
const PB = sm2Curve.ProjectivePoint.fromHex(publicKeyB);
let ZA = getZ(keypairA.publicKey, idA);
let ZB = getZ(publicKeyB, idB);
if (isRecipient) {
[ZA, ZB] = [ZB, ZA];
}
const rA = utils.hexToNumber(ephemeralKeypairA.privateKey);
const dA = utils.hexToNumber(keypairA.privateKey);
// 1.先算 tA
const x1 = RA.x;
// x1_ = 2^w + (x1 & (2^w - 1))
const x1_ = wPow2 + (x1 & wPow2Sub1);
// tA = (dA + x1b * rA) mod n
const tA = field.add(dA, field.mulN(x1_, rA));
// 2.算 U
// x2_ = 2^w + (x2 & (2^w - 1))
const x2 = RB.x;
const x2_ = field.add(wPow2, (x2 & wPow2Sub1));
// U = [h * tA](PB + x2_ * RB)
const U = RB.multiply(x2_).add(PB).multiply(tA);
// 3.算 KDF
// KA = KDF(xU || yU || ZA || ZB, kLen)
const xU = hexToArray(leftPad(utils.numberToHexUnpadded(U.x), 64));
const yU = hexToArray(leftPad(utils.numberToHexUnpadded(U.y), 64));
const KA = hkdf(utils.concatBytes(xU, yU, ZA, ZB), sharedKeyLength);
return KA;
}
//# sourceMappingURL=kx.js.map