diff options
author | Matthew Miller <matthew@millerti.me> | 2022-11-11 15:50:45 -0800 |
---|---|---|
committer | Matthew Miller <matthew@millerti.me> | 2022-11-11 15:50:45 -0800 |
commit | e5f0187693cb1521eb7f032adac2ca1005d4e406 (patch) | |
tree | 97b667439dfd8d87d4921e7af6b171391fab543d /packages/server/src/helpers | |
parent | b522a24a229d031ea0286f111179ac3bf30cfeca (diff) |
Refactor more to handle CBOR maps
Diffstat (limited to 'packages/server/src/helpers')
4 files changed, 67 insertions, 67 deletions
diff --git a/packages/server/src/helpers/convertPublicKeyToPEM.test.ts b/packages/server/src/helpers/convertPublicKeyToPEM.test.ts index 353a9eb..f7cd401 100644 --- a/packages/server/src/helpers/convertPublicKeyToPEM.test.ts +++ b/packages/server/src/helpers/convertPublicKeyToPEM.test.ts @@ -1,45 +1,45 @@ -import base64url from 'base64url'; -import cbor from 'cbor'; import { COSEKEYS } from './convertCOSEtoPKCS'; import { convertPublicKeyToPEM } from './convertPublicKeyToPEM'; +import * as cbor from './cbor'; +import * as uint8Array from './uint8Array'; -test('should return pem when input is base64URLString', () => { - const mockCOSEKey = new Map<number, number | Buffer>(); +test('should return pem - EC2', () => { + const mockEC2Key = new Map<number, number | Uint8Array>(); - const x = Buffer.from('gh9MmXjtmcHFesofqWZ6iuxSdAYgoPVvfJqpv1818lo', 'base64'); - const y = Buffer.from('3BDZHsNvKUb5VbyGPqcAFf4FGuPhJ2Xy215oWDw_1jc', 'base64'); - mockCOSEKey.set(COSEKEYS.kty, 2); - mockCOSEKey.set(COSEKEYS.alg, -7); - mockCOSEKey.set(COSEKEYS.crv, 1); - mockCOSEKey.set(COSEKEYS.x, x); - mockCOSEKey.set(COSEKEYS.y, y); + const x = uint8Array.fromHex('821f4c9978ed99c1c57aca1fa9667a8aec52740620a0f56f7c9aa9bf5f35f25a'); + const y = uint8Array.fromHex('dc10d91ec36f2946f955bc863ea70015fe051ae3e12765f2db5e68583c3fd637'); + mockEC2Key.set(COSEKEYS.kty, 2); + mockEC2Key.set(COSEKEYS.alg, -7); + mockEC2Key.set(COSEKEYS.crv, 1); + mockEC2Key.set(COSEKEYS.x, x); + mockEC2Key.set(COSEKEYS.y, y); - jest.spyOn(cbor, 'decodeAllSync').mockReturnValueOnce([mockCOSEKey]); - const input = base64url.toBuffer('test'); - const actual = convertPublicKeyToPEM(input); + const pubKeyCBOR = cbor.encode(mockEC2Key); + + const actual = convertPublicKeyToPEM(pubKeyCBOR); expect(actual).toEqual(`-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgh9MmXjtmcHFesofqWZ6iuxSdAYg\noPVvfJqpv1818lrcENkew28pRvlVvIY+pwAV/gUa4+EnZfLbXmhYPD/WNw== -----END PUBLIC KEY----- `); }); -test('should return pem when input is base64URLString', () => { - const mockCOSEKey = new Map<number, number | Buffer>(); +test('should return pem - RSA', () => { + const mockRSAKey = new Map<number, number | Buffer>(); const n = Buffer.from( '0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw', 'base64', ); const e = Buffer.from('AQAB', 'base64'); - mockCOSEKey.set(COSEKEYS.kty, 3); - mockCOSEKey.set(COSEKEYS.alg, -7); - mockCOSEKey.set(COSEKEYS.crv, 1); - mockCOSEKey.set(COSEKEYS.n, n); - mockCOSEKey.set(COSEKEYS.e, e); + mockRSAKey.set(COSEKEYS.kty, 3); + mockRSAKey.set(COSEKEYS.alg, -7); + mockRSAKey.set(COSEKEYS.crv, 1); + mockRSAKey.set(COSEKEYS.n, n); + mockRSAKey.set(COSEKEYS.e, e); + + const pubKeyCBOR = cbor.encode(mockRSAKey); - jest.spyOn(cbor, 'decodeAllSync').mockReturnValueOnce([mockCOSEKey]); - const input = base64url.toBuffer('test'); - const actual = convertPublicKeyToPEM(input); + const actual = convertPublicKeyToPEM(pubKeyCBOR); expect(actual).toEqual(`-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0vx7agoebGcQSuuPiLJX ZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tS @@ -58,25 +58,25 @@ test('should return pem when input is base64URLString', () => { mockCOSEKey.set(COSEKEYS.kty, 0); mockCOSEKey.set(COSEKEYS.alg, -7); - jest.spyOn(cbor, 'decodeAllSync').mockReturnValueOnce([mockCOSEKey]); - const input = base64url.toBuffer('test'); + const pubKeyCBOR = cbor.encode(mockCOSEKey); + try { - convertPublicKeyToPEM(input); + convertPublicKeyToPEM(pubKeyCBOR); } catch (err) { expect((err as Error).message).toEqual('Public key was missing kty'); } }); test('should raise error when kty is OKP (1)', () => { - const mockCOSEKey = new Map<number, number | Buffer>(); + const mockOKPKey = new Map<number, number | Buffer>(); - mockCOSEKey.set(COSEKEYS.kty, 1); - mockCOSEKey.set(COSEKEYS.alg, -7); + mockOKPKey.set(COSEKEYS.kty, 1); + mockOKPKey.set(COSEKEYS.alg, -7); + + const pubKeyCBOR = cbor.encode(mockOKPKey); - jest.spyOn(cbor, 'decodeAllSync').mockReturnValueOnce([mockCOSEKey]); - const input = base64url.toBuffer('test'); try { - convertPublicKeyToPEM(input); + convertPublicKeyToPEM(pubKeyCBOR); } catch (err) { expect((err as Error).message).toEqual('Could not convert public key type 1 to PEM'); } diff --git a/packages/server/src/helpers/convertPublicKeyToPEM.ts b/packages/server/src/helpers/convertPublicKeyToPEM.ts index 40c8c5f..ff8396b 100644 --- a/packages/server/src/helpers/convertPublicKeyToPEM.ts +++ b/packages/server/src/helpers/convertPublicKeyToPEM.ts @@ -1,27 +1,28 @@ import jwkToPem from 'jwk-to-pem'; -import { COSEKEYS, COSEKTY, COSECRV } from './convertCOSEtoPKCS'; -import { decodeCborFirst } from './decodeCbor'; +import { COSEKEYS, COSEKTY, COSECRV, COSEPublicKey } from './convertCOSEtoPKCS'; +import * as cbor from './cbor'; +import * as base64url from './base64url'; export function convertPublicKeyToPEM(publicKey: Uint8Array): string { let struct; try { - struct = decodeCborFirst(publicKey); + struct = cbor.decodeFirst<COSEPublicKey>(publicKey); } catch (err) { const _err = err as Error; throw new Error(`Error decoding public key while converting to PEM: ${_err.message}`); } - const kty = struct[COSEKEYS.kty]; + const kty = struct.get(COSEKEYS.kty); if (!kty) { throw new Error('Public key was missing kty'); } if (kty === COSEKTY.EC2) { - const crv = struct[COSEKEYS.crv]; - const x = struct[COSEKEYS.x]; - const y = struct[COSEKEYS.y]; + const crv = struct.get(COSEKEYS.crv); + const x = struct.get(COSEKEYS.x); + const y = struct.get(COSEKEYS.y); if (!crv) { throw new Error('Public key was missing crv (EC2)'); @@ -39,14 +40,14 @@ export function convertPublicKeyToPEM(publicKey: Uint8Array): string { kty: 'EC', // Specify curve as "P-256" from "p256" crv: COSECRV[crv as number].replace('p', 'P-'), - x: (x as Buffer).toString('base64'), - y: (y as Buffer).toString('base64'), + x: base64url.fromBuffer(x as Uint8Array, 'base64'), + y: base64url.fromBuffer(y as Uint8Array, 'base64'), }); return ecPEM; } else if (kty === COSEKTY.RSA) { - const n = struct[COSEKEYS.n]; - const e = struct[COSEKEYS.e]; + const n = struct.get(COSEKEYS.n); + const e = struct.get(COSEKEYS.e); if (!n) { throw new Error('Public key was missing n (RSA)'); @@ -58,8 +59,8 @@ export function convertPublicKeyToPEM(publicKey: Uint8Array): string { const rsaPEM = jwkToPem({ kty: 'RSA', - n: (n as Buffer).toString('base64'), - e: (e as Buffer).toString('base64'), + n: base64url.fromBuffer(n as Uint8Array, 'base64'), + e: base64url.fromBuffer(e as Uint8Array, 'base64'), }); return rsaPEM; diff --git a/packages/server/src/helpers/decodeAttestationObject.test.ts b/packages/server/src/helpers/decodeAttestationObject.test.ts index 1ba6bd0..b37d137 100644 --- a/packages/server/src/helpers/decodeAttestationObject.test.ts +++ b/packages/server/src/helpers/decodeAttestationObject.test.ts @@ -11,9 +11,9 @@ test('should decode base64url-encoded indirect attestationObject', () => { ), ); - expect(decoded.fmt).toEqual('none'); - expect(decoded.attStmt).toEqual({}); - expect(decoded.authData).toBeDefined(); + expect(decoded.get('fmt')).toEqual('none'); + expect(decoded.get('attStmt')).toEqual(new Map()); + expect(decoded.get('authData')).toBeDefined(); }); test('should decode base64url-encoded direct attestationObject', () => { @@ -38,8 +38,8 @@ test('should decode base64url-encoded direct attestationObject', () => { ), ); - expect(decoded.fmt).toEqual('fido-u2f'); - expect(decoded.attStmt.sig).toBeDefined(); - expect(decoded.attStmt.x5c).toBeDefined(); - expect(decoded.authData).toBeDefined(); + expect(decoded.get('fmt')).toEqual('fido-u2f'); + expect(decoded.get('attStmt').get('sig')).toBeDefined(); + expect(decoded.get('attStmt').get('x5c')).toBeDefined(); + expect(decoded.get('authData')).toBeDefined(); }); diff --git a/packages/server/src/helpers/decodeAttestationObject.ts b/packages/server/src/helpers/decodeAttestationObject.ts index bab6ced..9d08e33 100644 --- a/packages/server/src/helpers/decodeAttestationObject.ts +++ b/packages/server/src/helpers/decodeAttestationObject.ts @@ -1,13 +1,12 @@ -import { decodeCborFirst } from './decodeCbor'; +import * as cbor from './cbor'; /** * Convert an AttestationObject buffer to a proper object * * @param base64AttestationObject Attestation Object buffer */ -export function decodeAttestationObject(attestationObject: Buffer): AttestationObject { - const toCBOR: AttestationObject = decodeCborFirst(attestationObject); - return toCBOR; +export function decodeAttestationObject(attestationObject: Uint8Array): AttestationObject { + return cbor.decodeFirst<AttestationObject>(attestationObject); } export type AttestationFormat = @@ -20,17 +19,17 @@ export type AttestationFormat = | 'none'; export type AttestationObject = { - fmt: AttestationFormat; - attStmt: AttestationStatement; - authData: Buffer; + get(key: 'fmt'): AttestationFormat; + get(key: 'attStmt'): AttestationStatement; + get(key: 'authData'): Uint8Array; }; export type AttestationStatement = { - sig?: Buffer; - x5c?: Buffer[]; - response?: Buffer; - alg?: number; - ver?: string; - certInfo?: Buffer; - pubArea?: Buffer; + get(key: 'sig'): Uint8Array | undefined; + get(key: 'x5c'): Uint8Array[] | undefined; + get(key: 'response'): Uint8Array | undefined; + get(key: 'alg'): number | undefined; + get(key: 'ver'): string | undefined; + get(key: 'certInfo'): Uint8Array | undefined; + get(key: 'pubArea'): Uint8Array | undefined; }; |