【发布时间】:2020-08-27 17:33:21
【问题描述】:
我正在验证提供公钥的签名
MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEMyHD625uvsmGq4C43cQ9BnfN2xslVT5V1nOmAMP6qaRRUll3PB1JYmgSm+62sosG
经过大量研究,我认为这是ECDsaP192 标准密钥(如果我错了,请纠正我)。
所以密钥的分解是
30 13
06 07 2A 86 48 CE 3D 02 01
06 08 2A 86 48 CE 3D 03 01 01
03 32 00
04
33 21 C3 EB 6E 6E BE C9 86 AB 80 B8 DD C4 3D 6 77 CD DB 1B 25 55 3E 55 // Qx, 24 bytes
D6 73 A6 0 C3 FA A9 A4 51 52 59 77 3C 1D 49 62 68 12 9B EE B6 B2 8B 6 // Qy, 24 bytes
我看到了一个secp256r1 键的示例,它与我的情况非常相似,但我仍然无法让它为我工作。 我的代码:
private static readonly byte[] p192r1Prefix =
Convert.FromBase64String("MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAE");
private static readonly byte[] s_cngBlobPrefix = { 0x45, 0x43, 0x53, 0x31, 0x18, 0, 0, 0 };
void Main()
{
var pubkey = @"MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEMyHD625uvsmGq4C43cQ9BnfN2xslVT5V1nOmAMP6qaRRUll3PB1JYmgSm+62sosG";
var key = ImportECDsa256PublicKey(pubkey);
}
private static CngKey ImportECDsa256PublicKey(string base64)
{
byte[] subjectPublicKeyInfo = Convert.FromBase64String(base64);
byte[] prefix = p192r1Prefix;
byte[] cngBlob = new byte[s_cngBlobPrefix.Length + 48];
Buffer.BlockCopy(s_cngBlobPrefix, 0, cngBlob, 0, s_cngBlobPrefix.Length);
Buffer.BlockCopy(
subjectPublicKeyInfo,
p192r1Prefix.Length,
cngBlob,
s_cngBlobPrefix.Length,
48);
return CngKey.Import(cngBlob, CngKeyBlobFormat.EccPublicBlob); // Error: The parameter is incorrect.
}
编辑:使用 BouncyCastle
void Main()
{
// Documentation https://developer.apple.com/documentation/storekit/skadnetwork/verifying_an_install_validation_postback
var applePublicKey = @"MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEMyHD625uvsmGq4C43cQ9BnfN2xslVT5V1nOmAMP6qaRRUll3PB1JYmgSm+62sosG";
var keyBytes = Convert.FromBase64String(applePublicKey);
var param = GetPublicKeyParam(keyBytes);
var dataStr = "2.0" + '\u2063' + "com.example" + '\u2063' + "42" + '\u2063' + "525463029" + '\u2063' + "6aafb7a5-0170-41b5-bbe4-fe71dedf1e28" + '\u2063' + "1" + '\u2063' + "1234567891";
var data = Encoding.UTF8.GetBytes(dataStr);
var signature = "MDYCGQCsQ4y8d4BlYU9b8Qb9BPWPi+ixk/OiRysCGQDZZ8fpJnuqs9my8iSQVbJO/oU1AXUROYU=";
var sigBytes = Convert.FromBase64String(signature);
ISigner signer = SignerUtilities.GetSigner("SHA-256withECDSA");
signer.Init(false, param);
signer.BlockUpdate(data, 0, dataStr.Length);
Console.WriteLine(signer.VerifySignature(sigBytes));
}
private ECPublicKeyParameters GetPublicKeyParam(byte[] publicKeyBytes)
{
// parse based on asn1 format the content of the certificate
var asn1 = (Asn1Sequence)Asn1Object.FromByteArray(publicKeyBytes);
var at1 = (DerBitString)asn1[1];
var xyBytes = at1.GetBytes();
//retrieve preddefined parameters for P192(?) curve
X9ECParameters x9 = NistNamedCurves.GetByName("P-192");
//establish domain we will be looking for the x and y
ECDomainParameters domainParams = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed());
ECPublicKeyParameters publicKeyParams = new ECPublicKeyParameters(x9.Curve.DecodePoint(xyBytes), domainParams);
return publicKeyParams;
}
【问题讨论】:
-
您使用哪个 .NET 版本?
-
@Topaco 我正在使用 4.7.2
-
0x45, 0x43, 0x53, 0x31是标识 NIST P-256(又名 secp256r1)、here 而非您的曲线的神奇数字。对于 .NET Framework,BouncyCastle 是一种可能。哪种格式具有签名(r|s 或 ASN.1)或具有哪种长度?理想情况下,您可以发布可以使用发布的公钥验证的测试数据(明文和签名)。哪个摘要用于签名,SHA-256? -
@Topaco 我找不到 P192 的幻数,所以我使用了 0x45、0x43、0x53、0x31 ... 实际上我只是尝试了 BouncyCastle,它适用于公钥。签名是 ASN.1。我尝试将其转换为 r|s 但验证仍然没有运气。原始帖子已更新所有信息。
标签: c# .net cryptography public-key cng