Javascript ECDsaCng通过Windows上的C#验证来自Android WebAuthn的数据椭圆曲线签名
无论我做什么,我都无法让C#ECDsaCng VerifyData方法返回true。类似的代码适用于RSA签名和来自Windows Hello的数据,但Android/Samsung的EC加密让我感到困惑 断言.签名:-MEYCIQDi0OGHK2CRFpel6RWq26IjyWmJCfJnnaYvGWL/NBC6AWIZNWESDJ5UZFXDKVHENGYCKAEUZGJEYKIVJGFF/SNyd assertion.ClientDataJSON:-{“类型”:“webauthn.get”,“挑战”:“ZXLKAGJHY2LPAPJVXPJMU5PSXNJBLI1Y0NJNKLRFHWQ0O5LMV5SMXLSEFPT2PFMK1UVTVOAK14TWPBC0LTBHPJEUK2SWXSBGMZUXVJL0SWL3AVLYVMTJAM9PVKDWEMRDNWPIMJRJBPZLRL3RL1DBCEPJNFJJJRJRJJJRHDGN01MS1VPUKFXWFL0BDBRD1BKQUJVQ”,“原产地”:”https://localhost:3000,“androidPackageName”:“com.android.chrome”} pubKey.x:-CeE16bdD0ga/oiy/zFL1c70Cp/9me+HZzggzlTooWzU= pubKey.y:-N5l+MynIqzxgut+phBUNIOcI7DIv2uRXHkLCesK90Cg= 以下是代码段:-Javascript ECDsaCng通过Windows上的C#验证来自Android WebAuthn的数据椭圆曲线签名,javascript,c#,authentication,encryption,webauthn,Javascript,C#,Authentication,Encryption,Webauthn,无论我做什么,我都无法让C#ECDsaCng VerifyData方法返回true。类似的代码适用于RSA签名和来自Windows Hello的数据,但Android/Samsung的EC加密让我感到困惑 断言.签名:-MEYCIQDi0OGHK2CRFpel6RWq26IjyWmJCfJnnaYvGWL/NBC6AWIZNWESDJ5UZFXDKVHENGYCKAEUZGJEYKIVJGFF/SNyd assertion.ClientDataJSON:-{“类型”:“webauthn.get”
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")
{
byte[] ECDsaSig = convertFromASN1(sig);
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, keyType.Length);
Buffer.BlockCopy(keyLength, 0, keyImport, keyType.Length, keyLength.Length);
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, ECDsaSig))
{
Console.WriteLine("The signature is valid.");
}
else
{
Console.WriteLine("The signature is not valid.");
return FAIL_STATUS;
}
}
}
catch (Exception e)
{
return FAIL_STATUS;
}
}
阅读后,我意识到我必须将ASN.1签名转换为ECDsa友好格式,因此我这样做:-
internal byte[] convertFromASN1(byte[] sig)
{
const int DER = 48;
const int LENGTH_MARKER = 2;
if (sig.Length < 6 || sig[0] != DER || sig[1] != sig.Length - 2 || sig[2] != LENGTH_MARKER || sig[sig[3] + 4] != LENGTH_MARKER)
throw new ArgumentException("Invalid signature format.", "sig");
int rLen = sig[3];
int sLen = sig[rLen + 5];
byte[] newSig = new byte[rLen + sLen];
Buffer.BlockCopy(sig, 4, newSig, 0, rLen);
Buffer.BlockCopy(sig, 6 + rLen, newSig, rLen, sLen);
return newSig;
}
内部字节[]convertFromASN1(字节[]sig)
{
常数int DER=48;
const int LENGTH_MARKER=2;
如果(sig.Length<6 | | sig[0]!=DER | | sig[1]!=sig.Length-2 | | sig[2]!=Length| | sig[sig[3]+4]!=Length|MARKER)
抛出新的ArgumentException(“无效的签名格式。”,“sig”);
int-rLen=sig[3];
int sLen=sig[rLen+5];
byte[]newSig=新字节[rLen+sLen];
块拷贝(sig,4,newSig,0,rLen);
块拷贝(sig,6+rLen,newSig,rLen,sLen);
返回newSig;
}
但仍然没有乐趣:-(我做错了什么?请帮助。(用SHA256散列的ClientData)类似的方法应该可以:
if (pubKey.kty == "EC")
{
byte[] ecDsaSig = convertFromASN1(sig);
var point = new ECPoint
{
X = Convert.FromBase64String(pubKey.x),
Y = Convert.FromBase64String(pubKey.y),
};
var ecparams = new ECParameters
{
Q = point,
Curve = ECCurve.NamedCurves.nistP256
};
try
{
using (ECDsa ecdsa = ECDsa.Create(ecparams))
{
if (ecdsa.VerifyData(data, ecDsaSig, HashAlgorithmName.SHA256)
{
Console.WriteLine("The signature is valid.");
}
else
{
Console.WriteLine("The signature is not valid.");
return FAIL_STATUS;
}
}
}
catch (Exception e)
{
return FAIL_STATUS;
}
}
将ASN.1转换为.NET想要的IEEE p-1363格式可能非常棘手。一些指导和建议
如果你拿样本sig,你可以更好地想象分解,X从1025开始,以3227结束,Y从9987开始,以1469结束
这就是我目前正在做的事情。类似的事情应该会起作用:
if (pubKey.kty == "EC")
{
byte[] ecDsaSig = convertFromASN1(sig);
var point = new ECPoint
{
X = Convert.FromBase64String(pubKey.x),
Y = Convert.FromBase64String(pubKey.y),
};
var ecparams = new ECParameters
{
Q = point,
Curve = ECCurve.NamedCurves.nistP256
};
try
{
using (ECDsa ecdsa = ECDsa.Create(ecparams))
{
if (ecdsa.VerifyData(data, ecDsaSig, HashAlgorithmName.SHA256)
{
Console.WriteLine("The signature is valid.");
}
else
{
Console.WriteLine("The signature is not valid.");
return FAIL_STATUS;
}
}
}
catch (Exception e)
{
return FAIL_STATUS;
}
}
将ASN.1转换为.NET想要的IEEE p-1363格式可能非常棘手。一些指导和建议
如果你拿样本sig,你可以更好地想象分解,X从1025开始,以3227结束,Y从9987开始,以1469结束
我现在也是这样做的。像往常一样,亚历克斯,你是一个血腥的传奇。Stackoverflow更适合你在这里。像往常一样,亚历克斯,你是一个血腥的传奇。Stackoverflow更适合你在这里。