Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"node": ">=22.0.0"
},
"scripts": {
"build": "rm -rf dist && tsc -p tsconfig.build.cjs.json && tsc -p tsconfig.build.esm.json",
"build": "rm -rf dist && tsc -p tsconfig.build.cjs.json && tsc -p tsconfig.build.esm.json && node ./scripts/write-dist-package-json.mjs",
"format:check": "prettier -c \"src/**/*.ts\" \"test/**/*.ts\" \"demo/**/*.*\" *.json README.md",
"format:write": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"demo/**/*.*\" *.json README.md",
"lint": "eslint src/ test/",
Expand Down
15 changes: 15 additions & 0 deletions scripts/write-dist-package-json.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { mkdir, writeFile } from 'node:fs/promises';
import { join } from 'node:path';

// TypeScript emits `.js` files for both outputs, so each dist folder needs its
// own package boundary to tell Node whether to load those files as ESM or CJS.
const distDirs = [
['cjs', { type: 'commonjs' }],
['esm', { type: 'module' }],
];

for (const [dir, pkg] of distDirs) {
const outDir = join(process.cwd(), 'dist', dir);
await mkdir(outDir, { recursive: true });
await writeFile(join(outDir, 'package.json'), `${JSON.stringify(pkg, null, 2)}\n`);
}
19 changes: 13 additions & 6 deletions src/decryption/decryption.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { cipher, util } from 'node-forge';
import { EncodingVersions } from '../encoding-versions';
import { EncryptionKey } from '../encryption-key';
import { DerivedKeyOptions } from '../key-derivation/derived-key';
import { CipherStrategy, strategyToAlgorithm } from '../strategies';
import { binaryStringToBytesBuffer, bytesToBinaryString, deSerialize, encodeUtf8 } from '../util';
import forge from 'node-forge';
import { EncodingVersions } from '../encoding-versions.js';
import { EncryptionKey } from '../encryption-key.js';
import { DerivedKeyOptions } from '../key-derivation/derived-key.js';
import { CipherStrategy, strategyToAlgorithm } from '../strategies.js';
import {
binaryStringToBytesBuffer,
bytesToBinaryString,
deSerialize,
encodeUtf8,
} from '../util.js';

const { cipher, util } = forge;

interface IEncryptionOptions {
iv: string;
Expand Down
6 changes: 3 additions & 3 deletions src/digests/hmac-digest.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Hex, hmac } from 'node-forge';
import forge from 'node-forge';

export function hmacSha256Digest(key: string, message: string): Hex {
const hm = hmac.create();
export function hmacSha256Digest(key: string, message: string): string {
const hm = forge.hmac.create();
hm.start('sha256', key);
hm.update(message);
return hm.digest().toHex();
Expand Down
6 changes: 4 additions & 2 deletions src/encryption-key.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { random } from 'node-forge';
import { binaryStringToBytes, bytesToBinaryString, decodeSafe64, encodeSafe64 } from './util';
import forge from 'node-forge';
import { binaryStringToBytes, bytesToBinaryString, decodeSafe64, encodeSafe64 } from './util.js';

const { random } = forge;

/**
* SymmetricKey that can be used to encrypt and decrypt data
Expand Down
16 changes: 9 additions & 7 deletions src/encryption/encryption.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { cipher as forgeCipher, random, util } from 'node-forge';
import { EncryptionKey } from '../encryption-key';
import { IRandomKeyOptions } from '../key-derivation/derived-key';
import { generateDerivedKey } from '../key-derivation/pbkdf2-hmac';
import { SerializationFormat } from '../serialization-versions';
import { CipherStrategy } from '../strategies';
import { binaryStringToBytesBuffer, serialize } from '../util';
import forge from 'node-forge';
import { EncryptionKey } from '../encryption-key.js';
import { IRandomKeyOptions } from '../key-derivation/derived-key.js';
import { generateDerivedKey } from '../key-derivation/pbkdf2-hmac.js';
import { SerializationFormat } from '../serialization-versions.js';
import { CipherStrategy } from '../strategies.js';
import { binaryStringToBytesBuffer, serialize } from '../util.js';

const { cipher: forgeCipher, random, util } = forge;

export interface IEncryptionOptionsWithoutKey {
/***
Expand Down
20 changes: 10 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ if (typeof window !== 'undefined' && typeof (<any>window).global === 'undefined'
(<any>window).global = window;
}

export * from './decryption/decryption';
export * from './encryption/encryption';
export * from './key-derivation/derived-key';
export * from './key-derivation/pbkdf2-hmac';
export * from './key-pairs/rsa';
export * from './signing/rsa-signature';
export * from './strategies';
export * from './encryption-key';
export * from './digests/hmac-digest';
export * from './decryption/decryption.js';
export * from './encryption/encryption.js';
export * from './key-derivation/derived-key.js';
export * from './key-derivation/pbkdf2-hmac.js';
export * from './key-pairs/rsa.js';
export * from './signing/rsa-signature.js';
export * from './strategies.js';
export * from './encryption-key.js';
export * from './digests/hmac-digest.js';
export {
encode64,
decode64,
Expand All @@ -40,4 +40,4 @@ export {
generateEncryptionVerificationArtifacts,
keyLengthFromPublicKeyPem,
keyLengthFromPrivateKeyPem,
} from './util';
} from './util.js';
12 changes: 7 additions & 5 deletions src/key-derivation/derived-key.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { md, pkcs5, random } from 'node-forge';
import { EncodingVersions } from '../encoding-versions';
import { EncryptionKey } from '../encryption-key';
import { SerializationFormat } from '../serialization-versions';
import forge from 'node-forge';
import { EncodingVersions } from '../encoding-versions.js';
import { EncryptionKey } from '../encryption-key.js';
import { SerializationFormat } from '../serialization-versions.js';
import {
binaryStringToBytes,
binaryStringToBytesBuffer,
bytesBufferToBinaryString,
deSerializeDerivedKeyOptions,
encodeUtf8,
serializeDerivedKeyOptions,
} from '../util';
} from '../util.js';

const { md, pkcs5, random } = forge;

/**
* Most of these values are copied directly from the Ruby library
Expand Down
4 changes: 2 additions & 2 deletions src/key-derivation/pbkdf2-hmac.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { EncryptionKey } from '../encryption-key';
import { DerivedKeyOptions, IRandomKeyOptions, KeyDerivationStrategy } from './derived-key';
import { EncryptionKey } from '../encryption-key.js';
import { DerivedKeyOptions, IRandomKeyOptions, KeyDerivationStrategy } from './derived-key.js';

/**
* Given a password/phrase, derive a fixed-length key from it using Pbkdf2Hmac.
Expand Down
17 changes: 10 additions & 7 deletions src/key-pairs/rsa.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { pki } from 'node-forge';
import { SerializationFormat } from '../serialization-versions';
import { deSerialize, keyLengthFromPublicKeyPem, serialize } from '../util';
import forge from 'node-forge';
import type { pki as ForgePki } from 'node-forge';
import { SerializationFormat } from '../serialization-versions.js';
import { deSerialize, keyLengthFromPublicKeyPem, serialize } from '../util.js';

const { pki } = forge;

export function generateRSAKeyPair(
bits = 4096
Expand Down Expand Up @@ -28,8 +31,8 @@ export function encryptPrivateKeyWithPassword({
privateKeyPem: string;
password: string;
}) {
const publicKey = pki.privateKeyFromPem(privateKeyPem);
return pki.encryptRsaPrivateKey(publicKey, password);
const privateKey = pki.privateKeyFromPem(privateKeyPem);
return pki.encryptRsaPrivateKey(privateKey, password);
}

export async function encryptWithPublicKey(
Expand All @@ -44,7 +47,7 @@ export async function encryptWithPublicKey(
},
serializationFormat: SerializationFormat = SerializationFormat.latest_version
) {
const pk = pki.publicKeyFromPem(publicKeyPem) as pki.rsa.PublicKey;
const pk = pki.publicKeyFromPem(publicKeyPem) as ForgePki.rsa.PublicKey;
const encrypted = pk.encrypt(data, scheme);

const bitLength = keyLengthFromPublicKeyPem(publicKeyPem);
Expand Down Expand Up @@ -95,6 +98,6 @@ export async function decryptWithPrivateKey({
encrypted: string;
scheme?: RsaEncryptionScheme;
}) {
const pk = pki.decryptRsaPrivateKey(privateKeyPem, password) as pki.rsa.PrivateKey;
const pk = pki.decryptRsaPrivateKey(privateKeyPem, password) as ForgePki.rsa.PrivateKey;
return pk.decrypt(encrypted, scheme);
}
11 changes: 7 additions & 4 deletions src/signing/rsa-signature.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { md, pki } from 'node-forge';
import forge from 'node-forge';
import type { pki as ForgePki } from 'node-forge';
import {
binaryStringToBytes,
bytesToBinaryString,
decodeSafe64,
encodeSafe64,
keyLengthFromPrivateKeyPem,
} from '../util';
} from '../util.js';

const { md, pki } = forge;

export interface ISignature {
signature: string;
Expand All @@ -16,7 +19,7 @@ export interface ISignature {

export function signWithPrivateKey(privateKeyPem: string, data: Uint8Array): ISignature {
const mdDigest = md.sha256.create();
const key = pki.privateKeyFromPem(privateKeyPem) as pki.rsa.PrivateKey;
const key = pki.privateKeyFromPem(privateKeyPem) as ForgePki.rsa.PrivateKey;
mdDigest.update(bytesToBinaryString(data));
const signature = key.sign(mdDigest);
const keySize = keyLengthFromPrivateKeyPem(privateKeyPem);
Expand Down Expand Up @@ -52,7 +55,7 @@ export function loadRsaSignature(serializedPayload: string): ISignature {
}

export function verifyWithPublicKey(publicKeyPem: string, signatureObj: ISignature) {
const key = pki.publicKeyFromPem(publicKeyPem) as pki.rsa.PublicKey;
const key = pki.publicKeyFromPem(publicKeyPem) as ForgePki.rsa.PublicKey;
const mdDigest = md.sha256.create();
mdDigest.update(bytesToBinaryString(signatureObj.data));
return key.verify(mdDigest.digest().bytes(), signatureObj.signature);
Expand Down
15 changes: 9 additions & 6 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { BSON } from 'bson';
import { Buffer as _buffer } from 'buffer';
import { pki, random, util } from 'node-forge';
import forge from 'node-forge';
import type { pki as ForgePki } from 'node-forge';
import { parse as yamlParse, stringify as yamlStringify } from 'yaml';
import { IEncryptionArtifacts } from './encryption/encryption';
import { ICryppoSerializationArtifacts, IDerivedKey } from './key-derivation/derived-key';
import { SerializationFormat } from './serialization-versions';
import { IEncryptionArtifacts } from './encryption/encryption.js';
import { ICryppoSerializationArtifacts, IDerivedKey } from './key-derivation/derived-key.js';
import { SerializationFormat } from './serialization-versions.js';

const { pki, random, util } = forge;

// 65 is the version byte for encryption artefacts encoded with BSON
const ENCRYPTION_ARTEFACTS_CURRENT_VERSION = 'A';
Expand Down Expand Up @@ -234,7 +237,7 @@ export function generateEncryptionVerificationArtifacts() {
}

export function keyLengthFromPublicKeyPem(publicKeyPem: string) {
const pk = pki.publicKeyFromPem(publicKeyPem) as pki.rsa.PublicKey;
const pk = pki.publicKeyFromPem(publicKeyPem) as ForgePki.rsa.PublicKey;
// Undocumented functionality but was the only way I could find to get
// key length out of the public key.
// https://github.com/digitalbazaar/forge/blob/master/lib/rsa.js#L1244
Expand All @@ -243,7 +246,7 @@ export function keyLengthFromPublicKeyPem(publicKeyPem: string) {
}

export function keyLengthFromPrivateKeyPem(privateKey: string) {
const pk = pki.privateKeyFromPem(privateKey) as pki.rsa.PrivateKey;
const pk = pki.privateKeyFromPem(privateKey) as ForgePki.rsa.PrivateKey;
// Undocumented functionality but was the only way I could find to get
// key length out of the public key.
// https://github.com/digitalbazaar/forge/blob/master/lib/rsa.js#L1244
Expand Down
4 changes: 3 additions & 1 deletion test/compatibility/compatibility.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { readFileSync } from 'fs';
import { util } from 'node-forge';
import forge from 'node-forge';
import { join } from 'path';
import {
CipherStrategy,
Expand All @@ -20,6 +20,8 @@ import {
} from '../../src/util';
import Compat from './compat.json';

const { util } = forge;

describe('compatiblity test for all cryppo port', () => {
Object.values(Compat.encryption_with_derived_key).forEach((objToValidate: any, index) => {
it(`${index}. can successfully decrypt with AES-GCM Encryption and
Expand Down
4 changes: 3 additions & 1 deletion test/signing/rsa-signature.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { readFileSync } from 'fs';
import { util } from 'node-forge';
import forge from 'node-forge';
import { join } from 'path';
import { generateRSAKeyPair } from '../../src/key-pairs/rsa';
import {
Expand All @@ -14,6 +14,8 @@ import {
utf8ToBytes,
} from '../../src/util';

const { util } = forge;

describe('signing', () => {
const data =
'Sign me! 񵿁R冎𵵖HخGؼ𝕖ƶ򠈛#؉�櫙㢍̇扑󺥈揥񠥥C񫉫𐣚ˏϹ끣Ϧ{󘕌󶨇󫊶ᣏ܊㋅i͸񦉑s蹇ҏ)6LJ𺘘ⶴ襰Յ󠪐쵏q;kbͥ%T껕̶ݸh齉͌.瘟D־򆷦ɍéʛڴʼǭ񤻲j򑶭';
Expand Down