ОБНОВЛЕНИЕ: ===========
Возникла очень похожая проблема с Elliptical Curve, как и с RSA. VarifyData всегда возвращает false.
byte[] data = new byte[authData.Length + hashValClientData.Length];
Buffer.BlockCopy(authData, 0, data, 0, authData.Length);
Buffer.BlockCopy(hashValClientData, 0, data, authData.Length, hashValClientData.Length);
byte[] sig = Convert.FromBase64String(assertion.Signature);
if (pubKey.kty == "EC")
{
var keyType = new byte[] { 0x45, 0x43, 0x53, 0x31 }; // BCRYPT_ECDSA_PUBLIC_P256_MAGIC {E, C, S, 1}
var keyLength = new byte[] { 0x20, 0x00, 0x00, 0x00 }; // Key length 32
byte[] keyImport = new byte [72];
Buffer.BlockCopy(keyType, 0, keyImport, 0, 4);
Buffer.BlockCopy(keyLength, 0, keyImport, 4, 4);
Buffer.BlockCopy(Convert.FromBase64String(pubKey.x), 0, keyImport, 8, 32);
Buffer.BlockCopy(Convert.FromBase64String(pubKey.y), 0, keyImport, 40, 32);
try
{
using (ECDsaCng dsa = new ECDsaCng(CngKey.Import(keyImport, CngKeyBlobFormat.EccPublicBlob)))
{
dsa.HashAlgorithm = CngAlgorithm.Sha256;
if (dsa.VerifyData(data, sig))
{
Console.WriteLine("The signature is valid.");
}
else
{
Console.WriteLine("The signature is not valid.");
return FAIL_STATUS;
}
}
}
catch (Exception e)
{
return FAIL_STATUS;
}
}
Объект ECDsaCng и CngKey действительны, но метод VerifyData всегда возвращает false. Что-то не так с моими данными?
ClientDataJSON имеет экранирование косой черты из Android EC1, но не из Windows RSA.
===================
Я пытаюсь использовать C # для проверки учетных данных FIDO2 / WebAuthn, возвращаемых из Javascript navigator.credentials.get (). Аутентификатором здесь является Windows Hello (PIN-код). Метод VerifySignature продолжает возвращать недействительную подпись независимо от того, что я делаю. Я использую неправильный алгоритм RSA? Base64, когда этого быть не должно? Любые идеи?
Код Javascript: -
return navigator.credentials.get({
publicKey: getAssertionOptions
}).then(rawAssertion => {
var assertion = {
id: base64encode(rawAssertion.rawId),
clientDataJSON: arrayBufferToString(rawAssertion.response.clientDataJSON),
userHandle: base64encode(rawAssertion.response.userHandle),
signature: base64encode(rawAssertion.response.signature),
authenticatorData: base64encode(rawAssertion.response.authenticatorData)
};
Код C #: -
creds.Id = tempDB.Id;
creds.PublicKeyJwk = tempDB.PublicKeyJwk;
byte[] hashValClientData = _hash.ComputeHash(Encoding.Latin1.GetBytes(assertion.ClientDataJSON));
RSA rsa = RSA.Create();
PublicKey pubKey;
try
{
pubKey = JsonConvert.DeserializeObject<PublicKey>(creds.PublicKeyJwk);
}
catch (Exception ex)
{
return FAIL_STATUS;
}
RSAParameters keyInfo = new RSAParameters();
keyInfo.Modulus = Encoding.Latin1.GetBytes(Base64Decode(pubKey.n));
keyInfo.Exponent = Encoding.Latin1.GetBytes(Base64Decode(pubKey.e));
rsa.ImportParameters(keyInfo);
RSAPKCS1SignatureDeformatter rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa);
rsaDeformatter.SetHashAlgorithm("SHA256");
byte[] sig = Encoding.Latin1.GetBytes(Base64Decode(assertion.Signature));
if (rsaDeformatter.VerifySignature(hashValClientData, sig))
{
Console.WriteLine("The signature is valid.");
}
else
{
Console.WriteLine("The signature is not valid.");
}
public static string Base64Encode(string plainText)
{
var plainTextBytes = Encoding.Latin1.GetBytes(plainText);
return Convert.ToBase64String(plainTextBytes);
}
public static string Base64Decode(string base64EncodedData)
{
string paddedString = base64EncodedData;
int padding = base64EncodedData.Length % 4;
if (padding > 0 && padding < 3)
{
paddedString += "==".Substring(0, padding);
}
var base64EncodedBytes = Convert.FromBase64String(paddedString);
return Encoding.Latin1.GetString(base64EncodedBytes);
}
Вывод консоли браузера: -
=== ответ Утверждение === test.html: 211 Идентификатор (base64): gtCDzIXzuh0ZlblqiyMFf7f0 / TS2m2a8sLvbj3CtERo = test.html: 211 clientDataJSON: {Тип: webauthn.get, вызов: ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SmxlSEFpT2pFMk1UUTFNRFV6TURJc0ltbHpjeUk2SWxSbGMzUXVZMjl0SWl3aVlYVmtJam9pVkdWemRDNWpiMjBpZlEuUXdYVUdob3FQM1RGckhGV2pOOHNyZWVadFpMM2gtaUVpZk9jTWlzbHQxVQ, Происхождение: HTTPS: // локальный: 44362, crossOrigin: false, other_keys_can_be_added_here: не сравнивать clientDataJSON с шаблоном. } Test.html: 211 userHandle (base64): c29tZS51c2VyLmlk test.html: 211 подпись (base64): Gd0x / 28tLTKba9 / LRA + 7riJ4XygPgfAjwdVw3h / fxisWSU8OLbcfqu6K5bIFspnPrsTyA6xD9I + 5Sq / BAOalcAJCy46 / 39swTPF6 + 76F8Hx5GFNcXusMZw6PQZpEqALZkifF936hTBXCoVrYcl9NZ5 / jjd9zpFhSN90Ht / WEAl4DrvgnZ / NQa2klCpm4anDaZoYDcv9SykqtUv / CHNAtpSYgcfA8XVcDGG3ieefw1rii6g6chgTNfwhctIiqSkCBrLECavVUrbT6UpF + R2nIgexCyT8dKe8gVxvNaUeFnltSSkleOo / GUHzisseFjTow + R9yo4og / tuuS9PSWTR8WA == test.html: 211 AuthenticatorData (base64): SZYN5YgOjGh0NBcPZHZgW4 / krrmihjLHmVzzuoMdl2MFAAAAAQ ==