如何验证签名,从PEM文件加载PUBLIC KEY?

时间:2022-05-30 18:31:11

I'm posting this in the hope it saves somebody else the hours I lost on this really stupid problem involving converting formats of public keys. If anybody sees a simpler solution or a problem, please let me know!

我发布这个是希望它能节省其他人在这个涉及转换公钥格式这个非常愚蠢的问题上丢失的时间。如果有人看到更简单的解决方案或问题,请告诉我!

The eCommerce system I'm using sends me some data along with a signature. They also give me their public key in .pem format. The .pem file looks like this:

我正在使用的电子商务系统向我发送了一些数据和签名。他们还以.pem格式给我他们的公钥。 .pem文件如下所示:

-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe+hkicNP7ROHUssGNtHwiT2Ew HFrSk/qwrcq8v5metRtTTFPE/nmzSkRnTs3GMpi57rBdxBBJW5W9cpNyGUh0jNXc VrOSClpD5Ri2hER/GcNrxVRP7RlWOqB1C03q4QYmwjHZ+zlM4OUhCCAtSWflB4wC Ka1g88CjFwRw/PB9kwIDAQAB -----END PUBLIC KEY-----

----- BEGIN PUBLIC KEY ----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe + hkicNP7ROHUssGNtHwiT2Ew HFrSk / qwrcq8v5metRtTTFPE / nmzSkRnTs3GMpi57rBdxBBJW5W9cpNyGUh0jNXc VrOSClpD5Ri2hER / GcNrxVRP7RlWOqB1C03q4QYmwjHZ + zlM4OUhCCAtSWflB4wC Ka1g88CjFwRw / PB9kwIDAQAB ----- END PUBLIC KEY -----

Here's the magic code to turn the above into an "RSACryptoServiceProvider" which is capable of verifying the signature. Uses the BouncyCastle library, since .NET apparently (and appallingly cannot do it without some major headaches involving certificate files):

这是将上述内容转换为能够验证签名的“RSACryptoServiceProvider”的神奇代码。使用BouncyCastle库,因为.NET显然(并且在没有涉及证书文件的一些重大问题的情况下令人震惊地无法做到):

RSACryptoServiceProvider thingee;

using (var reader = File.OpenText(@"c:\pemfile.pem"))
{
    var x = new PemReader(reader);
    var y = (RsaKeyParameters)x.ReadObject();

    thingee = (RSACryptoServiceProvider)RSACryptoServiceProvider.Create();
    var pa = new RSAParameters();
    pa.Modulus = y.Modulus.ToByteArray();
    pa.Exponent = y.Exponent.ToByteArray();
    thingee.ImportParameters(pa);
}

And then the code to actually verify the signature:

然后是实际验证签名的代码:

var signature = ... //reads from the packet sent by the eCommerce system
var data = ... //reads from the packet sent by the eCommerce system
var sha = new SHA1CryptoServiceProvider();
byte[] hash = sha.ComputeHash(Encoding.ASCII.GetBytes(data));
byte[] bSignature = Convert.FromBase64String(signature);

///Verify signature, FINALLY:
var hasValidSig = thingee.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), bSignature);

1 个解决方案

#1


Potential problem: using Encoding.ASCII.GetBytes(data) is almost certainly the wrong way to get the hash. That means they can only send a hash which doesn't have any high bits set.

潜在问题:使用Encoding.ASCII.GetBytes(data)几乎肯定是获取哈希的错误方法。这意味着他们只能发送没有设置任何高位的哈希值。

If this is in a "packet" you should get the raw data from the packet as a byte array. If it is represented as text, it should be in some encoded form - e.g. hex or base64. What does the hash look like?

如果这是一个“数据包”,你应该从数据包中获取原始数据作为字节数组。如果它被表示为文本,它应该是某种编码形式 - 例如十六进制或base64。哈希是什么样的?

#1


Potential problem: using Encoding.ASCII.GetBytes(data) is almost certainly the wrong way to get the hash. That means they can only send a hash which doesn't have any high bits set.

潜在问题:使用Encoding.ASCII.GetBytes(data)几乎肯定是获取哈希的错误方法。这意味着他们只能发送没有设置任何高位的哈希值。

If this is in a "packet" you should get the raw data from the packet as a byte array. If it is represented as text, it should be in some encoded form - e.g. hex or base64. What does the hash look like?

如果这是一个“数据包”,你应该从数据包中获取原始数据作为字节数组。如果它被表示为文本,它应该是某种编码形式 - 例如十六进制或base64。哈希是什么样的?