C# 通过签名和 RSA public 密钥验证 Json 字符串
C# Verify Json string via signature and RSA public key
我正在为本地 Android 市场创建一个 IAP 插件,我认为它与 google 游戏具有相似的 API。
我建立一个 Android 方,它将 return 市场对统一的所有反应 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[]
来验证? (用编码还是什么???)
我搜索了很多,但搜索得越多越乱。
我是走错了路还是使用了错误的方法或者...?
- 为什么工作流程要复杂?
有人能帮帮我吗?
谢谢。
好的,我按顺序回答:
They use a hash algorithm to sign data and encrypt that hash with private key. I must decrypt signature with public key and compare hashes.
不,那是不正确的。您应该像目前一样使用签名验证方法。将签名视为哈希加密是不正确的;即使是最新的 RSA 标准也不遗余力地解释这一点。对于 RSA,内部填充方法不同。对于 ECDSA,无法使用相同的方案直接 encryption/decryption。
As I read on net first INTEGER is Modules and second INTEGER is Exponent
是的,虽然是拼写modulus,不是modules。它是 public 指数,还有私钥的私有指数。也没有大写字母。
How truly convert signature to byte[] to verify? (with encoding or what???)
Standard Base 64 已经在评论区提到了。请注意,密钥和签名大小并不常见(但这本身没问题)。
Why should workflow be complicated?
好吧,最后必须有人对其进行编码,而加密很难。但为了方便您:整个 ASN.1 结构称为 SubjectPublicKeyInfo 结构;如果您在 Internet 上查看,您会发现 pre-made 代码可以从这样的结构中导入。
最终验证结构:确保您使用正确的签名格式(RSA-PKCS#1 v1.5 或 RSA-PSS)并且您确切知道哪个 二进制文件 数据被提供给签名生成函数。例如,JSON 上的签名可以是 ASCII 或 UTF-8,也可以是 UTF-16 LE 或 BE。
最好问签名的创建者。
我正在为本地 Android 市场创建一个 IAP 插件,我认为它与 google 游戏具有相似的 API。
我建立一个 Android 方,它将 return 市场对统一的所有反应 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[]
来验证? (用编码还是什么???)
我搜索了很多,但搜索得越多越乱。
我是走错了路还是使用了错误的方法或者...?
- 为什么工作流程要复杂?
有人能帮帮我吗?
谢谢。
好的,我按顺序回答:
They use a hash algorithm to sign data and encrypt that hash with private key. I must decrypt signature with public key and compare hashes.
不,那是不正确的。您应该像目前一样使用签名验证方法。将签名视为哈希加密是不正确的;即使是最新的 RSA 标准也不遗余力地解释这一点。对于 RSA,内部填充方法不同。对于 ECDSA,无法使用相同的方案直接 encryption/decryption。
As I read on net first INTEGER is Modules and second INTEGER is Exponent
是的,虽然是拼写modulus,不是modules。它是 public 指数,还有私钥的私有指数。也没有大写字母。
How truly convert signature to byte[] to verify? (with encoding or what???)
Standard Base 64 已经在评论区提到了。请注意,密钥和签名大小并不常见(但这本身没问题)。
Why should workflow be complicated?
好吧,最后必须有人对其进行编码,而加密很难。但为了方便您:整个 ASN.1 结构称为 SubjectPublicKeyInfo 结构;如果您在 Internet 上查看,您会发现 pre-made 代码可以从这样的结构中导入。
最终验证结构:确保您使用正确的签名格式(RSA-PKCS#1 v1.5 或 RSA-PSS)并且您确切知道哪个 二进制文件 数据被提供给签名生成函数。例如,JSON 上的签名可以是 ASCII 或 UTF-8,也可以是 UTF-16 LE 或 BE。
最好问签名的创建者。