【发布时间】:2021-02-28 11:05:16
【问题描述】:
更新:===========
椭圆曲线的问题与我对 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# 验证从 Javascript navigator.credentials.get() 返回的 FIDO2/WebAuthn 凭据。这里的身份验证器是 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 id (base64): gtCDzIXzuh0ZlblqiyMFf7f0/TS2m2a8sLvbj3CtERo= test.html:211 clientDataJSON: {"type":"webauthn.get","challenge":"ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SmxlSEFpT2pFMk1UUTFNRFV6TURJc0ltbHpjeUk2SWxSbGMzUXVZMjl0SWl3aVlYVmtJam9pVkdWemRDNWpiMjBpZlEuUXdYVUdob3FQM1RGckhGV2pOOHNyZWVadFpMM2gtaUVpZk9jTWlzbHQxVQ","origin":"https://localhost:44362","crossOrigin":false,"other_keys_can_be_added_here": “不要将 clientDataJSON 与模板进行比较。”} test.html:211 用户句柄(base64):c29tZS51c2VyLmlk test.html:211 signature (base64): Gd0x/28tLTKba9/LRa+7riJ4XygPgfAjwdVw3h/fxisWSU8OLbcfqu6K5bIFspnPrsTyA6xD9I+5Sq/BAOalcAJCy46/39swTPF6+76F8Hx5GFNcXusMZw6PQZpEqALZkifF936hTBXCoVrYcl9NZ5/jjd9zpFhSN90Ht/WEAl4DrvgnZ/NQa2klCpm4anDaZoYDcv9SykqtUv/CHNAtpSYgcfA8XVcDGG3ieefw1rii6g6chgTNfwhctIiqSkCBrLECavVUrbT6UpF+R2nIgexCyT8dKe8gVxvNaUeFnltSSkleOo/GUHzisseFjTow+R9yo4og/tuuS9PSWTR8WA== test.html:211 验证器数据(base64):SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MFAAAAAQ==
【问题讨论】:
-
Latin1.GetBytes(Base64Decode()) 看起来很奇怪。 Base64 已经产生了字节。不用自己编写,只需使用 Convert.FromBase64String
标签: c# authentication rsa public-key-encryption webauthn