Я работаю над проверкой подписи, открытый ключ которой указан как 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;
}
0x45, 0x43, 0x53, 0x31
— это магический номер, который идентифицирует NIST P-256 (он же secp256r1), здесь, а не ваша кривая. Для .NET Framework возможен BouncyCastle. Какой формат имеет подпись (r|s или ASN.1) или какой длины? В идеале вы могли бы опубликовать тестовые данные (открытый текст и подпись), которые можно проверить с помощью опубликованного открытого ключа. Какой дайджест использовался для подписи SHA-256? - person user 9014097   schedule 28.08.2020