private void VerifyAssert(ReadOnlySpan <byte> authData, ReadOnlySpan <byte> signature, FidoExtensions extensions) { byte[] keyBytes = null; using (var fin = new StreamReader(File.OpenRead(PublicKey))) { var reader = new PemReader(fin); if (Type == KeyType.ECDSA) { ECPublicKeyParameters parameters = (ECPublicKeyParameters)reader.ReadObject(); var x = parameters.Q.XCoord.ToBigInteger().ToByteArray(); var y = parameters.Q.YCoord.ToBigInteger().ToByteArray(); keyBytes = new byte[64]; // Why? There seems to be an extra byte at the beginning sometimes Array.Copy(x, x.Length - 32, keyBytes, 0, 32); Array.Copy(y, y.Length - 32, keyBytes, 32, 32); } else if (Type == KeyType.RSA) { RsaKeyParameters parameters = (RsaKeyParameters)reader.ReadObject(); var mod = parameters.Modulus.ToByteArray(); var e = parameters.Exponent.ToByteArray(); keyBytes = new byte[mod.Length + e.Length]; mod.CopyTo(keyBytes, 0); e.CopyTo(keyBytes, mod.Length); } else if (Type == KeyType.EDDSA) { throw new NotSupportedException("Original example includes this but not sure why, it doesn't seem supported"); } else { throw new NotSupportedException("Unsupported key type"); } } using (var assert = new FidoAssertion()) { assert.SetClientData(Cd); assert.Rp = "localhost"; assert.Count = 1; assert.SetAuthData(authData, 0); assert.SetExtensions(extensions); if (UserPresenceRequired) { assert.SetUserPresenceRequired(true); } if (UserVerificationRequired) { assert.SetUserVerificationRequired(true); } assert.SetSignature(signature, 0); assert.Verify(0, FromKeyType(Type), keyBytes); } }
private void OnExecute() { Fido2Settings.Flags = FidoFlags.Debug; var ext = FidoExtensions.None; if (HMACSalt != null) { ext |= FidoExtensions.HmacSecret; } if (BlobKey != null) { ext |= FidoExtensions.LargeBlobKey; } using (var assert = new FidoAssertion()) { using (var dev = new FidoDevice()) { dev.Open(Device); if (ForceU2F) { dev.ForceU2F(); } assert.SetClientData(Cd); assert.Rp = "localhost"; assert.SetExtensions(ext); if (UserPresenceRequired) { assert.SetUserPresenceRequired(true); } if (UserVerificationRequired) { assert.SetUserVerificationRequired(true); } if (Timeout != 0) { dev.SetTimeout(TimeSpan.FromSeconds(Timeout)); } if (CredentialId != null) { var credId = File.ReadAllBytes(CredentialId); assert.AllowCredential(credId); } dev.GetAssert(assert, Pin); dev.Close(); } if (assert.Count != 1) { throw new Exception($"{assert.Count} signatures required"); } if (Pin != null) { UserVerificationRequired = true; } VerifyAssert(assert[0].AuthData, assert[0].Signature, ext); if (HMACSecret != null) { File.WriteAllBytes(HMACSecret, assert[0].HmacSecret.ToArray()); } } }