diff --git a/src/index.ts b/src/index.ts index e12af6c95..9da71f6ca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,7 +14,7 @@ setEngine('nodeEngine', webcrypto, cryptoEngine); //region Exports export { default as RelaynetError } from './lib/RelaynetError'; -export * from './lib/crypto_wrappers/keyGenerators'; +export * from './lib/crypto_wrappers/keys'; // PKI export { default as Certificate } from './lib/crypto_wrappers/x509/Certificate'; diff --git a/src/integration_tests/channelSession.test.ts b/src/integration_tests/channelSession.test.ts index b400db653..694daccf6 100644 --- a/src/integration_tests/channelSession.test.ts +++ b/src/integration_tests/channelSession.test.ts @@ -4,14 +4,15 @@ import bufferToArray from 'buffer-to-arraybuffer'; import * as pkijs from 'pkijs'; import { expectBuffersToEqual } from '../lib/_test_utils'; -import { getPkijsCrypto } from '../lib/crypto_wrappers/_utils'; import { SessionEnvelopedData } from '../lib/crypto_wrappers/cms/envelopedData'; -import { generateECDHKeyPair, generateRSAKeyPair } from '../lib/crypto_wrappers/keyGenerators'; +import { + derDeserializeECDHPublicKey, + generateECDHKeyPair, + generateRSAKeyPair, +} from '../lib/crypto_wrappers/keys'; import Certificate from '../lib/crypto_wrappers/x509/Certificate'; import { issueInitialDHKeyCertificate, issueNodeCertificate } from '../lib/pki'; -const cryptoEngine = getPkijsCrypto(); - const TOMORROW = new Date(); TOMORROW.setDate(TOMORROW.getDate() + 1); @@ -104,13 +105,10 @@ test('Encryption and decryption with subsequent DH keys', async () => { }); async function deserializeDhPublicKey(publicKeyDer: ArrayBuffer): Promise { - return cryptoEngine.importKey( - 'spki', - publicKeyDer, - { name: 'ECDH', namedCurve: 'P-256' }, - true, - [], - ); + return derDeserializeECDHPublicKey(Buffer.from(publicKeyDer), { + name: 'ECDH', + namedCurve: 'P-256', + }); } function checkRecipientInfo( diff --git a/src/lib/Parcel.spec.ts b/src/lib/Parcel.spec.ts index 025b9cbd2..26ca3a25a 100644 --- a/src/lib/Parcel.spec.ts +++ b/src/lib/Parcel.spec.ts @@ -2,7 +2,7 @@ import bufferToArray from 'buffer-to-arraybuffer'; import { generateStubCert, getMockContext } from './_test_utils'; -import { generateRSAKeyPair } from './crypto_wrappers/keyGenerators'; +import { generateRSAKeyPair } from './crypto_wrappers/keys'; import Parcel from './Parcel'; import * as serialization from './ramf/serialization'; diff --git a/src/lib/_test_utils.ts b/src/lib/_test_utils.ts index 23000bde9..e4216bec7 100644 --- a/src/lib/_test_utils.ts +++ b/src/lib/_test_utils.ts @@ -1,7 +1,7 @@ import { createHash } from 'crypto'; import * as pkijs from 'pkijs'; -import { generateRSAKeyPair } from './crypto_wrappers/keyGenerators'; +import { generateRSAKeyPair } from './crypto_wrappers/keys'; import Certificate from './crypto_wrappers/x509/Certificate'; import CertificateOptions from './crypto_wrappers/x509/CertificateOptions'; diff --git a/src/lib/crypto_wrappers/cms/envelopedData.spec.ts b/src/lib/crypto_wrappers/cms/envelopedData.spec.ts index 3f55341de..bea1e9f81 100644 --- a/src/lib/crypto_wrappers/cms/envelopedData.spec.ts +++ b/src/lib/crypto_wrappers/cms/envelopedData.spec.ts @@ -13,7 +13,7 @@ import { } from '../../_test_utils'; import * as oids from '../../oids'; import { issueInitialDHKeyCertificate } from '../../pki'; -import { generateECDHKeyPair, generateRSAKeyPair } from '../keyGenerators'; +import { generateECDHKeyPair, generateRSAKeyPair } from '../keys'; import Certificate from '../x509/Certificate'; import { deserializeContentInfo } from './_test_utils'; import CMSError from './CMSError'; diff --git a/src/lib/crypto_wrappers/cms/signedData.spec.ts b/src/lib/crypto_wrappers/cms/signedData.spec.ts index 000f298a9..79dbaf21b 100644 --- a/src/lib/crypto_wrappers/cms/signedData.spec.ts +++ b/src/lib/crypto_wrappers/cms/signedData.spec.ts @@ -12,7 +12,7 @@ import { sha256Hex, } from '../../_test_utils'; import * as oids from '../../oids'; -import { generateRSAKeyPair } from '../keyGenerators'; +import { generateRSAKeyPair } from '../keys'; import Certificate from '../x509/Certificate'; import { deserializeContentInfo } from './_test_utils'; import CMSError from './CMSError'; diff --git a/src/lib/crypto_wrappers/keyGenerators.spec.ts b/src/lib/crypto_wrappers/keyGenerators.spec.ts deleted file mode 100644 index 7cdf04d53..000000000 --- a/src/lib/crypto_wrappers/keyGenerators.spec.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { CryptoEngine } from 'pkijs'; - -import { getMockContext } from '../_test_utils'; -import { ECDHCurveName, generateECDHKeyPair, generateRSAKeyPair } from './keyGenerators'; - -describe('generateRsaKeyPair', () => { - test('Keys should be RSA', async () => { - const keyPair = await generateRSAKeyPair(); - - expect(keyPair.publicKey.algorithm.name).toMatch(/^RSA-/); - expect(keyPair.privateKey.algorithm.name).toMatch(/^RSA-/); - }); - - test('Keys should be extractable', async () => { - const keyPair = await generateRSAKeyPair(); - - expect(keyPair.publicKey.extractable).toBe(true); - expect(keyPair.privateKey.extractable).toBe(true); - }); - - describe('Modulus', () => { - test('Default modulus should be 2048', async () => { - const keyPair = await generateRSAKeyPair(); - // @ts-ignore - expect(keyPair.publicKey.algorithm.modulusLength).toBe(2048); - // @ts-ignore - expect(keyPair.privateKey.algorithm.modulusLength).toBe(2048); - }); - - test('Modulus > 2048 should be supported', async () => { - const modulus = 3072; - const keyPair = await generateRSAKeyPair({ modulus }); - // @ts-ignore - expect(keyPair.publicKey.algorithm.modulusLength).toBe(modulus); - // @ts-ignore - expect(keyPair.privateKey.algorithm.modulusLength).toBe(modulus); - }); - - test('Modulus < 2048 should not supported', async () => { - await expect(generateRSAKeyPair({ modulus: 1024 })).rejects.toThrow( - 'RSA modulus must be => 2048 per RS-018 (got 1024)', - ); - }); - }); - - describe('Hashing algorithm', () => { - test('SHA-256 should be used by default', async () => { - const keyPair = await generateRSAKeyPair(); - // @ts-ignore - expect(keyPair.publicKey.algorithm.hash.name).toBe('SHA-256'); - // @ts-ignore - expect(keyPair.privateKey.algorithm.hash.name).toBe('SHA-256'); - }); - - ['SHA-384', 'SHA-512'].forEach(hashingAlgorithm => { - test(`${hashingAlgorithm} should be supported`, async () => { - const keyPair = await generateRSAKeyPair({ hashingAlgorithm }); - // @ts-ignore - expect(keyPair.publicKey.algorithm.hash.name).toBe(hashingAlgorithm); - // @ts-ignore - expect(keyPair.privateKey.algorithm.hash.name).toBe(hashingAlgorithm); - }); - }); - - test('SHA-1 should not be supported', async () => { - await expect(generateRSAKeyPair({ hashingAlgorithm: 'SHA-1' })).rejects.toThrow( - 'SHA-1 is disallowed by RS-018', - ); - }); - }); -}); - -describe('generateDHKeyPair', () => { - const stubKey: CryptoKey = { - algorithm: { name: 'ECDH' }, - extractable: true, - type: 'private', - usages: [], - }; - const stubECDHKeyPair: CryptoKeyPair = { - privateKey: stubKey, - publicKey: stubKey, - }; - - beforeEach(() => { - jest - .spyOn(CryptoEngine.prototype, 'generateKey') - // @ts-ignore - .mockImplementationOnce(() => Promise.resolve(stubECDHKeyPair)); - }); - - afterEach(() => { - jest.restoreAllMocks(); - }); - - test('The result should be a DH key pair', async () => { - const keyPair = await generateECDHKeyPair(); - - expect(keyPair).toBe(stubECDHKeyPair); - - expect(CryptoEngine.prototype.generateKey).toBeCalledTimes(1); - const generateKeyCallArgs = getMockContext(CryptoEngine.prototype.generateKey).calls[0]; - const algorithm = generateKeyCallArgs[0]; - expect(algorithm).toHaveProperty('name', 'ECDH'); - }); - - test('NIST P-256 curve should be used by default', async () => { - await generateECDHKeyPair(); - - const generateKeyCallArgs = getMockContext(CryptoEngine.prototype.generateKey).calls[0]; - const algorithm = generateKeyCallArgs[0]; - expect(algorithm).toHaveProperty('namedCurve', 'P-256'); - }); - - test.each([['P-384', 'P-521']])('%s should also be supported', async curveName => { - await generateECDHKeyPair(curveName as ECDHCurveName); - - const generateKeyCallArgs = getMockContext(CryptoEngine.prototype.generateKey).calls[0]; - const algorithm = generateKeyCallArgs[0]; - expect(algorithm).toHaveProperty('namedCurve', curveName); - }); - - test('The key pair should be extractable', async () => { - await generateECDHKeyPair(); - - const generateKeyCallArgs = getMockContext(CryptoEngine.prototype.generateKey).calls[0]; - - const extractableFlag = generateKeyCallArgs[1]; - expect(extractableFlag).toBeTrue(); - }); - - test('deriveKey and deriveBits should be the only uses of the keys', async () => { - await generateECDHKeyPair(); - - const generateKeyCallArgs = getMockContext(CryptoEngine.prototype.generateKey).calls[0]; - - const keyUses = generateKeyCallArgs[2]; - expect(keyUses).toHaveLength(2); - expect(keyUses).toContain('deriveBits'); - expect(keyUses).toContain('deriveKey'); - }); -}); diff --git a/src/lib/crypto_wrappers/keyGenerators.ts b/src/lib/crypto_wrappers/keyGenerators.ts deleted file mode 100644 index e54746756..000000000 --- a/src/lib/crypto_wrappers/keyGenerators.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { getAlgorithmParameters } from 'pkijs'; - -import { getPkijsCrypto } from './_utils'; - -const cryptoEngine = getPkijsCrypto(); - -export type ECDHCurveName = 'P-256' | 'P-384' | 'P-521'; - -/** - * Generate an RSA key pair - * - * @param modulus The RSA modulus for the keys (2048 or greater). - * @param hashingAlgorithm The hashing algorithm (e.g., SHA-256, SHA-384, SHA-512). - * @throws Error If the modulus or the hashing algorithm is disallowed by RS-018. - */ -export async function generateRSAKeyPair({ - modulus = 2048, - hashingAlgorithm = 'SHA-256', -} = {}): Promise { - if (modulus < 2048) { - throw new Error(`RSA modulus must be => 2048 per RS-018 (got ${modulus})`); - } - - // RS-018 disallows MD5 and SHA-1, but only SHA-1 is supported in WebCrypto - if (hashingAlgorithm === 'SHA-1') { - throw new Error('SHA-1 is disallowed by RS-018'); - } - - const algorithm = getAlgorithmParameters('RSA-PSS', 'generatekey'); - // tslint:disable-next-line:no-object-mutation - (algorithm.algorithm.hash as Algorithm).name = hashingAlgorithm; - // tslint:disable-next-line:no-object-mutation - algorithm.algorithm.modulusLength = modulus; - - return cryptoEngine.generateKey(algorithm.algorithm, true, algorithm.usages); -} - -export async function generateECDHKeyPair( - curveName: ECDHCurveName = 'P-256', -): Promise { - return cryptoEngine.generateKey({ name: 'ECDH', namedCurve: curveName }, true, [ - 'deriveBits', - 'deriveKey', - ]); -} diff --git a/src/lib/crypto_wrappers/keys.spec.ts b/src/lib/crypto_wrappers/keys.spec.ts new file mode 100644 index 000000000..0a2f6c42d --- /dev/null +++ b/src/lib/crypto_wrappers/keys.spec.ts @@ -0,0 +1,274 @@ +// tslint:disable:no-let +import bufferToArray from 'buffer-to-arraybuffer'; +import { CryptoEngine } from 'pkijs'; + +import { expectBuffersToEqual } from '../_test_utils'; +import { + derDeserializeECDHPrivateKey, + derDeserializeECDHPublicKey, + derDeserializeRSAPrivateKey, + derDeserializeRSAPublicKey, + derSerializePrivateKey, + derSerializePublicKey, + ECDHCurveName, + generateECDHKeyPair, + generateRSAKeyPair, +} from './keys'; + +describe('generateRsaKeyPair', () => { + test('Keys should be RSA', async () => { + const keyPair = await generateRSAKeyPair(); + + expect(keyPair.publicKey.algorithm.name).toMatch(/^RSA-/); + expect(keyPair.privateKey.algorithm.name).toMatch(/^RSA-/); + }); + + test('Keys should be extractable', async () => { + const keyPair = await generateRSAKeyPair(); + + expect(keyPair.publicKey.extractable).toBe(true); + expect(keyPair.privateKey.extractable).toBe(true); + }); + + describe('Modulus', () => { + test('Default modulus should be 2048', async () => { + const keyPair = await generateRSAKeyPair(); + // @ts-ignore + expect(keyPair.publicKey.algorithm.modulusLength).toBe(2048); + // @ts-ignore + expect(keyPair.privateKey.algorithm.modulusLength).toBe(2048); + }); + + test('Modulus > 2048 should be supported', async () => { + const modulus = 3072; + const keyPair = await generateRSAKeyPair({ modulus }); + // @ts-ignore + expect(keyPair.publicKey.algorithm.modulusLength).toBe(modulus); + // @ts-ignore + expect(keyPair.privateKey.algorithm.modulusLength).toBe(modulus); + }); + + test('Modulus < 2048 should not supported', async () => { + await expect(generateRSAKeyPair({ modulus: 1024 })).rejects.toThrow( + 'RSA modulus must be => 2048 per RS-018 (got 1024)', + ); + }); + }); + + describe('Hashing algorithm', () => { + test('SHA-256 should be used by default', async () => { + const keyPair = await generateRSAKeyPair(); + // @ts-ignore + expect(keyPair.publicKey.algorithm.hash.name).toBe('SHA-256'); + // @ts-ignore + expect(keyPair.privateKey.algorithm.hash.name).toBe('SHA-256'); + }); + + ['SHA-384', 'SHA-512'].forEach(hashingAlgorithm => { + test(`${hashingAlgorithm} should be supported`, async () => { + const keyPair = await generateRSAKeyPair({ hashingAlgorithm }); + // @ts-ignore + expect(keyPair.publicKey.algorithm.hash.name).toBe(hashingAlgorithm); + // @ts-ignore + expect(keyPair.privateKey.algorithm.hash.name).toBe(hashingAlgorithm); + }); + }); + + test('SHA-1 should not be supported', async () => { + await expect(generateRSAKeyPair({ hashingAlgorithm: 'SHA-1' })).rejects.toThrow( + 'SHA-1 is disallowed by RS-018', + ); + }); + }); +}); + +describe('generateDHKeyPair', () => { + const stubKey: CryptoKey = { + algorithm: { name: 'ECDH' }, + extractable: true, + type: 'private', + usages: [], + }; + const stubECDHKeyPair: CryptoKeyPair = { + privateKey: stubKey, + publicKey: stubKey, + }; + + const mockGenerateKey = jest.spyOn(CryptoEngine.prototype, 'generateKey'); + beforeEach(() => { + mockGenerateKey.mockReset(); + // @ts-ignore + mockGenerateKey.mockImplementation(() => Promise.resolve(stubECDHKeyPair)); + }); + + afterAll(() => { + mockGenerateKey.mockRestore(); + }); + + test('The result should be a DH key pair', async () => { + const keyPair = await generateECDHKeyPair(); + + expect(keyPair).toBe(stubECDHKeyPair); + + expect(mockGenerateKey).toBeCalledTimes(1); + const generateKeyCallArgs = mockGenerateKey.mock.calls[0]; + const algorithm = generateKeyCallArgs[0]; + expect(algorithm).toHaveProperty('name', 'ECDH'); + }); + + test('NIST P-256 curve should be used by default', async () => { + await generateECDHKeyPair(); + + const generateKeyCallArgs = mockGenerateKey.mock.calls[0]; + const algorithm = generateKeyCallArgs[0]; + expect(algorithm).toHaveProperty('namedCurve', 'P-256'); + }); + + test.each([['P-384', 'P-521']])('%s should also be supported', async curveName => { + await generateECDHKeyPair(curveName as ECDHCurveName); + + const generateKeyCallArgs = mockGenerateKey.mock.calls[0]; + const algorithm = generateKeyCallArgs[0]; + expect(algorithm).toHaveProperty('namedCurve', curveName); + }); + + test('The key pair should be extractable', async () => { + await generateECDHKeyPair(); + + const generateKeyCallArgs = mockGenerateKey.mock.calls[0]; + + const extractableFlag = generateKeyCallArgs[1]; + expect(extractableFlag).toBeTrue(); + }); + + test('deriveKey and deriveBits should be the only uses of the keys', async () => { + await generateECDHKeyPair(); + + const generateKeyCallArgs = mockGenerateKey.mock.calls[0]; + const keyUses = generateKeyCallArgs[2]; + expect(keyUses).toHaveLength(2); + expect(keyUses).toContain('deriveBits'); + expect(keyUses).toContain('deriveKey'); + }); +}); + +describe('Key serializers', () => { + let stubKeyPair: CryptoKeyPair; + beforeAll(async () => { + stubKeyPair = await generateRSAKeyPair(); + }); + + const stubExportedKeyDer = bufferToArray(Buffer.from('Hey')); + const mockExportKey = jest.spyOn(CryptoEngine.prototype, 'exportKey'); + beforeEach(async () => { + mockExportKey.mockReset(); + mockExportKey.mockResolvedValue(stubExportedKeyDer); + }); + + afterAll(() => { + mockExportKey.mockRestore(); + }); + + test('derSerializePublicKey should convert public key to buffer', async () => { + const publicKeyDer = await derSerializePublicKey(stubKeyPair.publicKey); + + expect(publicKeyDer).toBeInstanceOf(Buffer); + expectBuffersToEqual(publicKeyDer, Buffer.from(stubExportedKeyDer)); + + expect(mockExportKey).toBeCalledTimes(1); + expect(mockExportKey).toBeCalledWith('spki', stubKeyPair.publicKey); + }); + + test('derSerializePrivateKey should convert private key to buffer', async () => { + const privateKeyDer = await derSerializePrivateKey(stubKeyPair.privateKey); + + expect(privateKeyDer).toBeInstanceOf(Buffer); + expectBuffersToEqual(privateKeyDer, Buffer.from(stubExportedKeyDer)); + + expect(mockExportKey).toBeCalledTimes(1); + expect(mockExportKey).toBeCalledWith('pkcs8', stubKeyPair.privateKey); + }); +}); + +describe('Key deserializers', () => { + const stubKeyDer = Buffer.from('Hey'); + const rsaAlgorithmOptions: RsaHashedImportParams = { name: 'RSA-PSS', hash: { name: 'SHA-256' } }; + const ecdhAlgorithmOptions: EcKeyImportParams = { name: 'ECDH', namedCurve: 'P-256' }; + + let stubKeyPair: CryptoKeyPair; + beforeAll(async () => { + stubKeyPair = await generateRSAKeyPair(); + }); + const mockImportKey = jest.spyOn(CryptoEngine.prototype, 'importKey'); + beforeEach(async () => { + mockImportKey.mockClear(); + }); + + afterAll(() => { + mockImportKey.mockRestore(); + }); + + test('derDeserializeRSAPublicKey should convert DER public key to RSA key', async () => { + mockImportKey.mockResolvedValueOnce(stubKeyPair.publicKey); + + const publicKey = await derDeserializeRSAPublicKey(stubKeyDer, rsaAlgorithmOptions); + + expect(publicKey).toBe(stubKeyPair.publicKey); + expect(mockImportKey).toBeCalledTimes(1); + expect(mockImportKey).toBeCalledWith( + 'spki', + bufferToArray(stubKeyDer), + rsaAlgorithmOptions, + true, + ['verify'], + ); + }); + + test('derDeserializeRSAPrivateKey should convert DER private key to RSA key', async () => { + mockImportKey.mockResolvedValueOnce(stubKeyPair.privateKey); + + const privateKey = await derDeserializeRSAPrivateKey(stubKeyDer, rsaAlgorithmOptions); + + expect(privateKey).toBe(stubKeyPair.privateKey); + expect(mockImportKey).toBeCalledTimes(1); + expect(mockImportKey).toBeCalledWith( + 'pkcs8', + bufferToArray(stubKeyDer), + rsaAlgorithmOptions, + true, + ['sign'], + ); + }); + + test('derDeserializeECDHPublicKey should convert DER public key to ECDH key', async () => { + mockImportKey.mockResolvedValueOnce(stubKeyPair.publicKey); + + const publicKey = await derDeserializeECDHPublicKey(stubKeyDer, ecdhAlgorithmOptions); + + expect(publicKey).toBe(stubKeyPair.publicKey); + expect(mockImportKey).toBeCalledTimes(1); + expect(mockImportKey).toBeCalledWith( + 'spki', + bufferToArray(stubKeyDer), + ecdhAlgorithmOptions, + true, + [], + ); + }); + + test('derDeserializeECDHPrivateKey should convert DER private key to ECDH key', async () => { + mockImportKey.mockResolvedValueOnce(stubKeyPair.privateKey); + + const privateKey = await derDeserializeECDHPrivateKey(stubKeyDer, ecdhAlgorithmOptions); + + expect(privateKey).toBe(stubKeyPair.privateKey); + expect(mockImportKey).toBeCalledTimes(1); + expect(mockImportKey).toBeCalledWith( + 'pkcs8', + bufferToArray(stubKeyDer), + ecdhAlgorithmOptions, + true, + ['deriveBits', 'deriveKey'], + ); + }); +}); diff --git a/src/lib/crypto_wrappers/keys.ts b/src/lib/crypto_wrappers/keys.ts new file mode 100644 index 000000000..30f033079 --- /dev/null +++ b/src/lib/crypto_wrappers/keys.ts @@ -0,0 +1,103 @@ +import bufferToArray from 'buffer-to-arraybuffer'; +import { getAlgorithmParameters } from 'pkijs'; + +import { getPkijsCrypto } from './_utils'; + +const cryptoEngine = getPkijsCrypto(); + +export type ECDHCurveName = 'P-256' | 'P-384' | 'P-521'; + +//region Key generators + +/** + * Generate an RSA key pair + * + * @param modulus The RSA modulus for the keys (2048 or greater). + * @param hashingAlgorithm The hashing algorithm (e.g., SHA-256, SHA-384, SHA-512). + * @throws Error If the modulus or the hashing algorithm is disallowed by RS-018. + */ +export async function generateRSAKeyPair({ + modulus = 2048, + hashingAlgorithm = 'SHA-256', +} = {}): Promise { + if (modulus < 2048) { + throw new Error(`RSA modulus must be => 2048 per RS-018 (got ${modulus})`); + } + + // RS-018 disallows MD5 and SHA-1, but only SHA-1 is supported in WebCrypto + if (hashingAlgorithm === 'SHA-1') { + throw new Error('SHA-1 is disallowed by RS-018'); + } + + const algorithm = getAlgorithmParameters('RSA-PSS', 'generatekey'); + // tslint:disable-next-line:no-object-mutation + (algorithm.algorithm.hash as Algorithm).name = hashingAlgorithm; + // tslint:disable-next-line:no-object-mutation + algorithm.algorithm.modulusLength = modulus; + + return cryptoEngine.generateKey(algorithm.algorithm, true, algorithm.usages); +} + +export async function generateECDHKeyPair( + curveName: ECDHCurveName = 'P-256', +): Promise { + return cryptoEngine.generateKey({ name: 'ECDH', namedCurve: curveName }, true, [ + 'deriveBits', + 'deriveKey', + ]); +} + +//endregion + +//region Key serialization + +export async function derSerializePublicKey(publicKey: CryptoKey): Promise { + const publicKeyDer = await cryptoEngine.exportKey('spki', publicKey); + return Buffer.from(publicKeyDer); +} + +export async function derSerializePrivateKey(privateKey: CryptoKey): Promise { + const keyDer = (await cryptoEngine.exportKey('pkcs8', privateKey)) as ArrayBuffer; + return Buffer.from(keyDer); +} + +//endregion + +//region key deserialization + +export async function derDeserializeRSAPublicKey( + publicKeyDer: Buffer, + algorithmOptions: RsaHashedImportParams, +): Promise { + return cryptoEngine.importKey('spki', bufferToArray(publicKeyDer), algorithmOptions, true, [ + 'verify', + ]); +} + +export async function derDeserializeECDHPublicKey( + publicKeyDer: Buffer, + algorithmOptions: EcKeyImportParams, +): Promise { + return cryptoEngine.importKey('spki', bufferToArray(publicKeyDer), algorithmOptions, true, []); +} + +export async function derDeserializeRSAPrivateKey( + publicKeyDer: Buffer, + algorithmOptions: RsaHashedImportParams, +): Promise { + return cryptoEngine.importKey('pkcs8', bufferToArray(publicKeyDer), algorithmOptions, true, [ + 'sign', + ]); +} + +export async function derDeserializeECDHPrivateKey( + publicKeyDer: Buffer, + algorithmOptions: EcKeyImportParams, +): Promise { + return cryptoEngine.importKey('pkcs8', bufferToArray(publicKeyDer), algorithmOptions, true, [ + 'deriveBits', + 'deriveKey', + ]); +} + +//endregion diff --git a/src/lib/crypto_wrappers/x509/Certificate.spec.ts b/src/lib/crypto_wrappers/x509/Certificate.spec.ts index 2cf2f2ee7..af6379b16 100644 --- a/src/lib/crypto_wrappers/x509/Certificate.spec.ts +++ b/src/lib/crypto_wrappers/x509/Certificate.spec.ts @@ -6,7 +6,7 @@ import * as pkijs from 'pkijs'; import { expectPromiseToReject, generateStubCert, sha256Hex } from '../../_test_utils'; import * as oids from '../../oids'; import { deserializeDer, getPkijsCrypto } from '../_utils'; -import { generateRSAKeyPair } from '../keyGenerators'; +import { generateRSAKeyPair } from '../keys'; import Certificate from './Certificate'; import CertificateError from './CertificateError'; diff --git a/src/lib/pki.spec.ts b/src/lib/pki.spec.ts index 04c8b5507..e1a27ee2e 100644 --- a/src/lib/pki.spec.ts +++ b/src/lib/pki.spec.ts @@ -3,7 +3,7 @@ import * as pkijs from 'pkijs'; import { expectPromiseToReject, generateStubCert, getMockContext, sha256Hex } from './_test_utils'; import { getPkijsCrypto } from './crypto_wrappers/_utils'; -import { generateRSAKeyPair } from './crypto_wrappers/keyGenerators'; +import { generateRSAKeyPair } from './crypto_wrappers/keys'; import Certificate from './crypto_wrappers/x509/Certificate'; import CertificateOptions from './crypto_wrappers/x509/CertificateOptions'; import { diff --git a/src/lib/ramf/Message.spec.ts b/src/lib/ramf/Message.spec.ts index c8b13eaf0..0141d2c02 100644 --- a/src/lib/ramf/Message.spec.ts +++ b/src/lib/ramf/Message.spec.ts @@ -3,7 +3,7 @@ import bufferToArray from 'buffer-to-arraybuffer'; import * as jestDateMock from 'jest-date-mock'; import { generateStubCert } from '../_test_utils'; -import { generateRSAKeyPair } from '../crypto_wrappers/keyGenerators'; +import { generateRSAKeyPair } from '../crypto_wrappers/keys'; import Certificate from '../crypto_wrappers/x509/Certificate'; import { StubMessage } from './_test_utils'; diff --git a/src/lib/ramf/serialization.spec.ts b/src/lib/ramf/serialization.spec.ts index d9346470c..78773d868 100644 --- a/src/lib/ramf/serialization.spec.ts +++ b/src/lib/ramf/serialization.spec.ts @@ -13,7 +13,7 @@ import { getPromiseRejection, } from '../_test_utils'; import * as cmsSignedData from '../crypto_wrappers/cms/signedData'; -import { generateRSAKeyPair } from '../crypto_wrappers/keyGenerators'; +import { generateRSAKeyPair } from '../crypto_wrappers/keys'; import Certificate from '../crypto_wrappers/x509/Certificate'; import { NON_ASCII_STRING, StubMessage } from './_test_utils'; import RAMFSyntaxError from './RAMFSyntaxError';