From 7ca9e61e931f5b1ca82f8847525a404a64178981 Mon Sep 17 00:00:00 2001 From: Andreas Coroiu Date: Mon, 29 Jan 2024 13:50:30 +0100 Subject: [PATCH] [PM-5731] feat: return public key in DER format --- .../Services/Fido2AuthenticatorService.cs | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/Core/Services/Fido2AuthenticatorService.cs b/src/Core/Services/Fido2AuthenticatorService.cs index b8c675d06..887c45bbf 100644 --- a/src/Core/Services/Fido2AuthenticatorService.cs +++ b/src/Core/Services/Fido2AuthenticatorService.cs @@ -102,7 +102,7 @@ namespace Bit.Core.Services CredentialId = GuidToRawFormat(credentialId), AttestationObject = EncodeAttestationObject(authData), AuthData = authData, - PublicKey = Array.Empty(), + PublicKey = keyPair.publicKey.ExportDer(), PublicKeyAlgorithm = (int) Fido2AlgorithmIdentifier.ES256, }; } catch (NotAllowedError) { @@ -286,19 +286,11 @@ namespace Bit.Core.Services // TODO: Move this to a separate service private (PublicKey publicKey, byte[] privateKey) GenerateKeyPair() { - using (System.Security.Cryptography.ECDsa dsa = System.Security.Cryptography.ECDsa.Create()) - { - dsa.GenerateKey(System.Security.Cryptography.ECCurve.NamedCurves.nistP256); - var privateKey = dsa.ExportPkcs8PrivateKey(); + var dsa = System.Security.Cryptography.ECDsa.Create(); + dsa.GenerateKey(System.Security.Cryptography.ECCurve.NamedCurves.nistP256); + var privateKey = dsa.ExportPkcs8PrivateKey(); - System.Security.Cryptography.ECParameters parameters = dsa.ExportParameters(true); - - return ( - new PublicKey { - X = parameters.Q.X, - Y = parameters.Q.Y - }, privateKey); - } + return (new PublicKey(dsa), privateKey); } private Fido2CredentialView CreateCredentialView(Fido2AuthenticatorMakeCredentialParams makeCredentialsParams, byte[] privateKey) @@ -326,9 +318,9 @@ namespace Bit.Core.Services bool userPresence, int counter, byte[] credentialId = null, - PublicKey? publicKey = null + PublicKey publicKey = null ) { - var isAttestation = credentialId != null && publicKey.HasValue; + var isAttestation = credentialId != null && publicKey != null; List authData = new List(); @@ -363,7 +355,7 @@ namespace Bit.Core.Services }; attestedCredentialData.AddRange(credentialIdLength); attestedCredentialData.AddRange(credentialId); - attestedCredentialData.AddRange(publicKey.Value.ToCose()); + attestedCredentialData.AddRange(publicKey.ExportCose()); authData.AddRange(attestedCredentialData); } @@ -434,12 +426,23 @@ namespace Bit.Core.Services return Guid.Parse(guid).ToByteArray(); } - private struct PublicKey + private class PublicKey { - public byte[] X { get; set; } - public byte[] Y { get; set; } + private readonly System.Security.Cryptography.ECDsa _dsa; - public byte[] ToCose() + public PublicKey(System.Security.Cryptography.ECDsa dsa) { + _dsa = dsa; + } + + public byte[] X => _dsa.ExportParameters(false).Q.X; + public byte[] Y => _dsa.ExportParameters(false).Q.Y; + + public byte[] ExportDer() + { + return _dsa.ExportSubjectPublicKeyInfo(); + } + + public byte[] ExportCose() { var result = new CborWriter(CborConformanceMode.Ctap2Canonical); result.WriteStartMap(5);