Files
self/circuits/tests/utils/generateMockInputsRsaPss.ts
2025-06-04 11:37:32 +02:00

100 lines
3.1 KiB
TypeScript

import * as forge from 'node-forge';
import { SignatureAlgorithm } from '@selfxyz/common/utils/types';
import { hexToDecimal } from '@selfxyz/common/utils/bytes';
import { bytesToBigDecimal } from '@selfxyz/common/utils/bytes';
import { getNAndK } from '@selfxyz/common/utils/passports/passport';
import { splitToWords } from '@selfxyz/common/utils/bytes';
export const generateMockRsaPssInputs = (
signatureAlgorithm: SignatureAlgorithm,
saltLength: number
) => {
const [sigAlg, hashAlgorithm, exponent, modulusLength] = signatureAlgorithm.split('_');
// Generate RSA key pair
const keypair = forge.pki.rsa.generateKeyPair({
bits: parseInt(modulusLength),
e: parseInt(exponent),
});
const message = 'helloworld';
// Create message hash
const md = forge.md[hashAlgorithm].create();
md.update(forge.util.binary.raw.encode(Buffer.from(message)));
const messageHash = md.digest().bytes();
const messageBits = Array.from(messageHash)
.map((char: string) => {
const byte = char.charCodeAt(0);
return Array.from({ length: 8 }, (_, i) => (byte >> (7 - i)) & 1);
})
.flat();
// Create PSS signature
const pss = forge.pss.create({
md: forge.md[hashAlgorithm].create(),
mgf: forge.mgf.mgf1.create(forge.md[hashAlgorithm].create()),
saltLength,
});
const signatureBytes = keypair.privateKey.sign(md, pss);
const signature = Array.from(signatureBytes, (c: string) => c.charCodeAt(0));
// Get modulus from public key
const modulus = keypair.publicKey.n.toString(16);
const { n, k } = getNAndK(signatureAlgorithm);
return {
signature: splitToWords(BigInt(bytesToBigDecimal(signature)), n, k),
modulus: splitToWords(BigInt(hexToDecimal(modulus)), n, k),
message: messageBits,
n,
k,
};
};
export const generateMalleableRsaPssInputs = (
signatureAlgorithm: SignatureAlgorithm,
saltLength: number
) => {
const [sigAlg, hashAlgorithm, exponent, modulusLength] = signatureAlgorithm.split('_');
// Generate RSA key pair
const keypair = forge.pki.rsa.generateKeyPair({
bits: parseInt(modulusLength),
e: parseInt(exponent),
});
const message = 'helloworld';
const md = forge.md[hashAlgorithm].create();
md.update(forge.util.binary.raw.encode(Buffer.from(message)));
const messageHash = md.digest().bytes();
// Create valid signature
const pss = forge.pss.create({
md: forge.md[hashAlgorithm].create(),
mgf: forge.mgf.mgf1.create(forge.md[hashAlgorithm].create()),
saltLength,
});
const signatureBytes = keypair.privateKey.sign(md, pss);
const signature = Array.from(signatureBytes, (c: string) => c.charCodeAt(0));
const modulus = BigInt('0x' + keypair.publicKey.n.toString(16));
const sigValue = BigInt(bytesToBigDecimal(signature));
const malleableValue = sigValue + modulus;
const { n, k } = getNAndK(signatureAlgorithm);
return {
signature: splitToWords(malleableValue, n, k),
modulus: splitToWords(modulus, n, k),
message: Array.from(messageHash)
.map((char: string) => {
const byte = char.charCodeAt(0);
return Array.from({ length: 8 }, (_, i) => (byte >> (7 - i)) & 1);
})
.flat(),
};
};