Skip to content

Commit

Permalink
Update jsbt
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmillr committed Jan 18, 2025
1 parent 7572e12 commit 34ba17e
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 96 deletions.
56 changes: 7 additions & 49 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,14 @@ name: Publish release
on:
release:
types: [created]
workflow_dispatch:
jobs:
publish-jsr:
name: Publish to JSR.io
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4
- run: npm install -g jsr
- run: jsr publish
publish-npm:
name: Publish to NPM
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4
with:
node-version: 22
registry-url: 'https://registry.npmjs.org'
cache: npm
- run: npm ci
- run: npm run build
- run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
standalone:
name: Upload files to GitHub Releases
runs-on: ubuntu-latest
release-js:
name: "jsbt v0.3.0" # Should match commit below
uses: paulmillr/jsbt/.github/workflows/release.yml@973650a225c0344aa5f993a6cd63835a262077e9
with:
build-path: test/build
secrets:
NPM_PUBLISH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4
with:
node-version: 22
registry-url: 'https://registry.npmjs.org'
cache: npm
- run: npm ci
- run: npm run build
- run: |
cd build
npm ci
npm run build:release
cd ..
- run: gh release upload ${{ github.event.release.tag_name }} build/`npx jsbt outfile`
env:
GH_TOKEN: ${{ github.token }}
4 changes: 2 additions & 2 deletions .github/workflows/test-js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ on:
- pull_request
jobs:
test-js:
name: 'JS v0.2.2' # v0.2.2 == commit below
uses: paulmillr/jsbt/.github/workflows/test-js.yml@986dbfea9667eeb0e81bf606cbe9ed169fea89b2
name: "jsbt v0.3.0" # Should match commit below
uses: paulmillr/jsbt/.github/workflows/test-js.yml@973650a225c0344aa5f993a6cd63835a262077e9
17 changes: 9 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
"@noble/hashes": "1.7.0"
},
"devDependencies": {
"@paulmillr/jsbt": "0.2.1",
"micro-should": "0.5.0",
"@paulmillr/jsbt": "0.3.0",
"micro-should": "0.5.1",
"prettier": "3.1.1",
"typescript": "5.5.2"
},
Expand Down Expand Up @@ -64,7 +64,7 @@
"format": "prettier --write src",
"test": "node test/index.js",
"test:bun": "bun test/index.js",
"test:deno": "deno test/index.js"
"test:deno": "deno --allow-env --allow-read test/index.js"
},
"keywords": [
"rsa",
Expand Down
12 changes: 9 additions & 3 deletions src/dh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export type DHGroup = {
g: bigint; // Generator
};

export const DHGroups = {
export const DHGroups: Record<string, DHGroup> = {
modp1: {
p: BigInt(
'0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd1' +
Expand Down Expand Up @@ -209,7 +209,13 @@ export const DHGroups = {
* @param group well-known modp group or {p: bigint, g: bigint};
* @returns
*/
export const DH = (group: keyof DHGroup | DHGroup) => {
export const DH = (
group: keyof DHGroup | DHGroup
): {
randomPrivateKey(): Uint8Array;
getPublicKey(privateKey: Uint8Array): Uint8Array;
getSharedSecret(privateA: Uint8Array, publicB: Uint8Array): Uint8Array;
} => {
if (typeof group === 'string')
group = (DHGroups as Record<string, DHGroup>)[group as keyof DHGroup];
if (!group) throw new Error('DH: wrong group');
Expand All @@ -234,4 +240,4 @@ export const DH = (group: keyof DHGroup | DHGroup) => {
};
};

export const diffieHellman = DH;
export const diffieHellman: typeof DH = DH;
19 changes: 10 additions & 9 deletions src/dsa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,25 @@ import {
bytesToNumber,
getFieldBytesLength,
getMinHashLength,
Hash,
type Hash,
I2OSP,
invert,
mapHashToField,
mod,
numberToBytes,
OS2IP,
pow,
RandFn,
type RandFn,
} from './utils.js';

export class DERErr extends Error {
constructor(m = '') {
super(m);
}
}
export const DER = {
// asn.1 DER encoding utils
Err: class DERErr extends Error {
constructor(m = '') {
super(m);
}
},
Err: DERErr satisfies typeof DERErr as typeof DERErr,
_parseInt(data: Uint8Array): { d: bigint; l: Uint8Array } {
const { Err: E } = DER;
if (data.length < 2 || data[0] !== 0x02) throw new E('Invalid signature integer tag');
Expand Down Expand Up @@ -199,7 +200,7 @@ export function genDSAParams(
hash: Hash,
index: number,
seed?: Uint8Array | number,
randFn = randomBytes
randFn: typeof randomBytes = randomBytes
): DSAProvableParams {
if (typeof hash !== 'function') throw new Error('wrong hash');
const res = genDSAPrimes(L, N, hash, seed, randFn);
Expand Down Expand Up @@ -339,7 +340,7 @@ export const DSA = (params: DSAParams) => {
};
};

export const _TEST = {
export const _TEST: any = {
genDSAPrimes,
genDSAGenerator,
};
4 changes: 2 additions & 2 deletions src/elgamal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const ElGamal = ({ p, g }: ElGamalParams) => {
randomPrivateKey(): bigint {
return randomBigInt(pBytes, 2n, p - 1n); // [2, p-1)
},
getPublicKey(privateKey: bigint) {
getPublicKey(privateKey: bigint): bigint {
if (typeof privateKey !== 'bigint') throw new Error('privateKey should be bigint');
return pow(g, privateKey, p);
},
Expand All @@ -56,7 +56,7 @@ export const ElGamal = ({ p, g }: ElGamalParams) => {
const c2 = (message * yk) % p;
return { ct1: c1, ct2: c2 };
},
decrypt(privateKey: bigint, ciphertext: { ct1: bigint; ct2: bigint }) {
decrypt(privateKey: bigint, ciphertext: { ct1: bigint; ct2: bigint }): bigint {
if (typeof privateKey !== 'bigint') throw new Error('privateKey should be bigint');
if (typeof ciphertext.ct1 !== 'bigint' || typeof ciphertext.ct2 !== 'bigint')
throw new Error('invalid ciphertext');
Expand Down
8 changes: 4 additions & 4 deletions src/primality.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { randomBytes } from '@noble/hashes/utils';
import { gcd, mod, numberToBytes, pow, RandFn, randomBits } from './utils.js';
import { gcd, mod, numberToBytes, pow, type RandFn, randomBits } from './utils.js';

// Non-deterministic Miller-Rabin test over random bases (multiple iterations).
// This test is probabilistic and may produce false positives (pseudoprimes).
Expand Down Expand Up @@ -66,7 +66,7 @@ export function millerRabin(w: bigint, iterations: number, randFn: RandFn = rand
}

// Deterministic version of Miller-Rabin test with fixed base
export function millerRabinBaseTest(w: bigint, base: bigint) {
export function millerRabinBaseTest(w: bigint, base: bigint): boolean {
return millerRabin(w, 1, (len) => numberToBytes(base, len));
}

Expand Down Expand Up @@ -189,7 +189,7 @@ function checkSieve(n: bigint) {
* @param randFn
* @returns true if probable prime
*/
export function bailliePSW(n: bigint) {
export function bailliePSW(n: bigint): boolean {
const sieveRes = checkSieve(n);
if (sieveRes !== undefined) return sieveRes;
// BPSW does single iteration of M-R with fixed base 2
Expand All @@ -212,7 +212,7 @@ export function isProbablePrime(n: bigint, iters: number, randFn: RandFn = rando
return lucas(n);
}

export function isProbablePrimeRSA(n: bigint, randFn: RandFn = randomBytes) {
export function isProbablePrimeRSA(n: bigint, randFn: RandFn = randomBytes): boolean {
// - https://crypto.stackexchange.com/questions/104265/iteration-count-for-enhanced-miller-rabin
// - https://github.com/openssl/openssl/blob/master/crypto/bn/bn_rsa_fips186_4.c
const nLen = n.toString(2).length;
Expand Down
52 changes: 36 additions & 16 deletions src/rsa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { sha384, sha512, sha512_224, sha512_256 } from '@noble/hashes/sha512';
import { concatBytes, createView, hexToBytes, randomBytes } from '@noble/hashes/utils';
import { isProbablePrimeRSA } from './primality.js';
import {
Hash,
type Hash,
I2OSP,
OS2IP,
RandFn,
type RandFn,
ensureBytes,
gcd,
invert,
Expand Down Expand Up @@ -226,7 +226,11 @@ function RSAVP1(publicKey: { n: bigint; e: bigint }, s: bigint): bigint | false
* @param e - The public exponent.
* @returns An object containing the public key and the private key.
*/
export function keygen(nlen: number, e: bigint = 0x10001n, randFn: RandFn = randomBytes) {
export function keygen(
nlen: number,
e: bigint = 0x10001n,
randFn: RandFn = randomBytes
): { publicKey: { e: bigint; n: bigint }; privateKey: { d: bigint; n: bigint } } {
if (!Number.isSafeInteger(nlen) || nlen <= 0) throw new Error('wrong nlen');
const { p, q } = IFCPrimes(nlen, e, undefined, undefined, randFn);
const n = p * q;
Expand Down Expand Up @@ -458,10 +462,14 @@ export const PKCS1_KEM: KEM = {
},
};

export interface IPKCS {
verify(publicKey: PublicKey, M: Uint8Array, S: Uint8Array): boolean;
sign(privateKey: PrivateKey, M: Uint8Array): Uint8Array;
}
/**
* RSASSA-PKCS1-v1_5: old Signature Scheme with Appendix (SSA) as first standardized in version 1.5 of PKCS #1.
*/
const PKCS1 = (hash: Hash, prefix: string) => ({
const PKCS1 = (hash: Hash, prefix: string): IPKCS => ({
verify(publicKey: PublicKey, M: Uint8Array, S: Uint8Array): boolean {
validatePublicKey(publicKey);
M = ensureBytes('message', M);
Expand Down Expand Up @@ -490,35 +498,47 @@ const PKCS1 = (hash: Hash, prefix: string) => ({
});

// Encoded OIDs
export const PKCS1_SHA1 = /* @__PURE__ */ PKCS1(sha1, '3021300906052b0e03021a05000414');
export const PKCS1_SHA224 = /* @__PURE__ */ PKCS1(sha224, '302d300d06096086480165030402040500041c');
export const PKCS1_SHA256 = /* @__PURE__ */ PKCS1(sha256, '3031300d060960864801650304020105000420');
export const PKCS1_SHA384 = /* @__PURE__ */ PKCS1(sha384, '3041300d060960864801650304020205000430');
export const PKCS1_SHA512 = /* @__PURE__ */ PKCS1(sha512, '3051300d060960864801650304020305000440');
export const PKCS1_SHA512_224 = /* @__PURE__ */ PKCS1(
export const PKCS1_SHA1: IPKCS = /* @__PURE__ */ PKCS1(sha1, '3021300906052b0e03021a05000414');
export const PKCS1_SHA224: IPKCS = /* @__PURE__ */ PKCS1(
sha224,
'302d300d06096086480165030402040500041c'
);
export const PKCS1_SHA256: IPKCS = /* @__PURE__ */ PKCS1(
sha256,
'3031300d060960864801650304020105000420'
);
export const PKCS1_SHA384: IPKCS = /* @__PURE__ */ PKCS1(
sha384,
'3041300d060960864801650304020205000430'
);
export const PKCS1_SHA512: IPKCS = /* @__PURE__ */ PKCS1(
sha512,
'3051300d060960864801650304020305000440'
);
export const PKCS1_SHA512_224: IPKCS = /* @__PURE__ */ PKCS1(
sha512_224,
'302d300d06096086480165030402050500041c'
);
export const PKCS1_SHA512_256 = /* @__PURE__ */ PKCS1(
export const PKCS1_SHA512_256: IPKCS = /* @__PURE__ */ PKCS1(
sha512_256,
'3031300d060960864801650304020605000420'
);
// https://github.com/usnistgov/ACVP-Server/issues/257#issuecomment-1502669140
export const PKCS1_SHA3_224 = /* @__PURE__ */ PKCS1(
export const PKCS1_SHA3_224: IPKCS = /* @__PURE__ */ PKCS1(
sha3_224,
'302d300d06096086480165030402070500041c'
);
export const PKCS1_SHA3_256 = /* @__PURE__ */ PKCS1(
export const PKCS1_SHA3_256: IPKCS = /* @__PURE__ */ PKCS1(
sha3_256,
'3031300d060960864801650304020805000420'
);
export const PKCS1_SHA3_384 = /* @__PURE__ */ PKCS1(
export const PKCS1_SHA3_384: IPKCS = /* @__PURE__ */ PKCS1(
sha3_384,
'3041300d060960864801650304020905000430'
);
export const PKCS1_SHA3_512 = /* @__PURE__ */ PKCS1(
export const PKCS1_SHA3_512: IPKCS = /* @__PURE__ */ PKCS1(
sha3_512,
'3051300d060960864801650304020a05000440'
);

export const _TEST = { RSAEP, RSADP, RSASP1 };
export const _TEST: any = { RSAEP, RSADP, RSASP1 };

0 comments on commit 34ba17e

Please sign in to comment.