【发布时间】:2018-08-18 21:57:31
【问题描述】:
我正在为本地 Android 市场创建一个 IAP 插件,我认为它的 API 与 google play 相似。
我构建了一个 Android 端,它将来自市场的所有响应返回到统一 c# side。
所有部分工作正常,但我不知道如何验证响应的签名。
我是密码学的新手,每天都在搜索这方面的内容。
如果我错了,请纠正我。
- 他们使用
hash算法对数据进行签名并使用private key加密hash。
我必须用public key解密签名并比较哈希值。
这是我的public key (Base64):
MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBrwDltnT/AaF3oMt+F3lza5JEvce0GLS1L9v9Z53lQ3LNluGk0eI2ukgWm7tAiIOLQgn11Sb9mW2VWkYTWGnZ1AZtY0GwdUQJUr7u3CWNznE6XH4UCVOVhGDCLnFrG8BcfDelhcfReGZQ3izOefhc4Oq6vZf5PfLwximK+FH27fR6XL8vg3yyK4LSwT764Dfd6H3IGes6EdTx/C3C690jdyMvhi2Q3qBiqfepHzW/jV8CAwEAAQ==
此密钥为ASN.1 DER 格式。
我把它分解并找到这个数据:
SEQUENCE
SEQUENCE
OBJECT IDENTIFIER 1.2.840.113549.1.1.1 rsaEncryption(PKCS #1)
NULL
BIT STRING
SEQUENCE
INTEGER 969837669069837851043825067021609343597253227631794160042862620526559…
INTEGER 65537
- 正如我在网上看到的第一个
INTEGER是Modules和第二个INTEGER是Exponent
所以在c#中写这样的代码=>
var parameter = new RSAParameters
{
Modulus = HexToByteArray(/* "first_INTEGET" */),
Exponent = BitConverter.GetBytes(/* "second_INTEGER" */)
};
市场向我发送Json,如下所示:
{"orderId": "0j8oJgE0Bett-neB", "purchaseToken": "0j8oJgE0Bett-neB", "developerPayload": "payload", "packageName": "com.some.market", "purchaseState": 0, "purchaseTime": 1520676644872, "productId": "card-1"}
签名是这样的:
hTFeQd25PZJ2DhGmXd0eO+C+oBeWsg983I4e5ztXtKAUrOIaNBaqAxHU3vW8acBs1I9fE5cxx/DI/sQGY4QSvpDnSm9aYz3do3joHPOXIVvXjSJfejxwzp9DKMUPd6LrgtxkaGevG+94NuKHFxpCdZlovEPXRJZyEznbASuYLqeW0KjP3jnvvw2O5iNlQRdh98h4Q18bSsaxq9zaRKExFLHkhNf/yO5m84kRB1G8
我正在寻找一种方法来执行此操作,但我不知道哪种方法对我来说是正确的。 我的验证码是这样的:
using (var rsa = new RSACryptoServiceProvider())
{
rsa.ImportParameters(parameter);
var hash = new SHA1Managed();
bool dataOK =
rsa.VerifyData(hash.ComputeHash(Encoding.UTF8.GetBytes(json)), CryptoConfig.MapNameToOID("SHA1"), Encoding.UTF8.GetBytes(signature));
}
- 如何真正将
signature转换为byte[]进行验证? (用编码还是什么???)
我搜索了很多,但搜索越多越混乱。
我是走错了路还是使用了错误的方法或......?
- 工作流程为什么要复杂?
有人可以帮帮我吗?
谢谢。
【问题讨论】:
-
模数和公共指数只是十进制整数,而不是十六进制。
-
非常感谢,如何将这个长十进制转换为字节数组?
-
使用它创建一个 BigInteger,然后调用
ToByteArray()方法,然后使用您必须编写的简单方法反转字节顺序。BigInteger.ToByteArray()返回一个 little-endian 数组,但 RSAParameters 字段是 big-endian。 -
签名也是base-64,你为什么要用
Encoding.UTF8.GetBytes呢? -
至于“工作流程为什么要复杂?” - 这是因为无论出于何种原因,ASN.1 DER 都不是 .NET 加密的“本机”格式。通常使用其他格式(例如原始公钥\私钥或 xml 格式的密钥)。所以这很复杂,因为没有内置方法可以将 ASN.1 DER 编码密钥转换为 .NET 预期的格式(但您可以在互联网上找到执行此操作的代码)。此外,您可能对 BouncyCastle(.NET 的自定义密码库)有更好的运气。
标签: c# unity3d cryptography signature public-key