From 3ccaf7658b07202c8497b46942c11b498e39b4b2 Mon Sep 17 00:00:00 2001 From: Berend Sliedrecht <61358536+berendsliedrecht@users.noreply.github.com> Date: Tue, 26 Nov 2024 17:55:41 +0100 Subject: [PATCH] fix(x509): encode key usages as a bit string (#2115) fix(x509): encode key usages as a bit mask Signed-off-by: Berend Sliedrecht --- .../core/src/modules/x509/X509Certificate.ts | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/core/src/modules/x509/X509Certificate.ts b/packages/core/src/modules/x509/X509Certificate.ts index ae2591e0a..8cae40538 100644 --- a/packages/core/src/modules/x509/X509Certificate.ts +++ b/packages/core/src/modules/x509/X509Certificate.ts @@ -25,7 +25,7 @@ type ExtensionObjectIdentifier = string type SubjectAlternativeNameExtension = Array<{ type: 'url' | 'dns'; value: string }> type AuthorityKeyIdentifierExtension = { keyId: string } type SubjectKeyIdentifierExtension = { keyId: string } -type KeyUsageExtension = { usage: KeyUsage } +type KeyUsageExtension = { usage: number } type ExtensionValues = | SubjectAlternativeNameExtension @@ -108,7 +108,7 @@ export class X509Certificate { } else if (e instanceof x509.SubjectAlternativeNameExtension) { return { [e.type]: JSON.parse(JSON.stringify(e.names)) as SubjectAlternativeNameExtension } } else if (e instanceof x509.KeyUsagesExtension) { - return { [e.type]: { usage: e.usages as unknown as KeyUsage } } + return { [e.type]: { usage: e.usages as number } } } // TODO: We could throw an error when we don't understand the extension? @@ -173,10 +173,21 @@ export class X509Certificate { return keyIds?.[0] } - public get keyUsage() { - const usage = this.getMatchingExtensions(id_ce_keyUsage)?.map((e) => e.usage) + public get keyUsage(): Array { + const keyUsages = this.getMatchingExtensions(id_ce_keyUsage)?.map((e) => e.usage) - return usage ?? [] + if (keyUsages && keyUsages.length > 1) { + throw new X509Error('Multiple Key Usages are not allowed') + } + + if (keyUsages) { + return Object.values(KeyUsage) + .filter((key): key is number => typeof key === 'number') + .filter((flagValue) => (keyUsages[0] & flagValue) === flagValue) + .map((flagValue) => flagValue as KeyUsage) + } + + return [] } public static async createSelfSigned( @@ -199,8 +210,7 @@ export class X509Certificate { const x509Extensions: Array = [ new x509.SubjectKeyIdentifierExtension(hexPublicKey), - new x509.KeyUsagesExtension(x509.KeyUsageFlags.digitalSignature), - new x509.KeyUsagesExtension(x509.KeyUsageFlags.keyCertSign), + new x509.KeyUsagesExtension(x509.KeyUsageFlags.digitalSignature | x509.KeyUsageFlags.keyCertSign), ] if (includeAuthorityKeyIdentifier) {