使用Base64编码的公钥来验证RSA签名

问题描述 投票:17回答:3

简而言之,这是我的问题:

private string publicKeyString = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVGUzbydMZS+fnkGTsUkDKEyFOGwghR234d5GjPnMIC0RFtXtw2tdcNM8I9Qk+h6fnPHiA7r27iHBfdxTP3oegQJWpbY2RMwSmOs02eQqpKx4QtIjWqkKk2Gmck5cll9GCoI8AUAA5e0D02T0ZgINDmo5yGPhGAAmqYrm8YiupwQIDAQAB";

/* Some transformation required, using publicKeyString to initiate a new RSACryptoServiceProvider object
*/

//for now:
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

byte[] selfComputedHash = new byte[]; //left out of the example
byte[] signature = new byte[];

bool result = rsa.VerifyHash(selfComputedHash, CryptoConfig.MapNameToOID("SHA1"), signature);

如您所见,问题是使用给定的Base64编码公钥字符串启动新的RSACryptoServiceProvider。我已经能够使用对象RSAParameters进行实例化,该对象使用OpenSSL shell命令从用于此公钥字符串的Modulus和Exponent加载byte []。但由于此公钥可能在将来发生变化,因此我希望能够将其以原始形式存储在数据库中。必须有一种更直接的方式来解决这个问题。

到目前为止,我读过的很多例子都是通过从密钥容器对象导出和导入生成的私钥和公钥来避免这个问题,并在同一段代码中使用它,因此不会“转移”密钥一些字符串形式的内存不足。有些人在StackOverflow和其他网站上都表达了同样的问题,但我还没有找到令人满意的答案。

任何想法都非常受欢迎。

背景信息:我的通信伙伴从可变长度的输入字符串计算一个20字节的SHA1哈希值,该字符串由ASCII编码消息的几个字段中包含的信息组成。然后使用我的合作伙伴的私钥对此哈希进行RSA签名,并将ASCII消息一起发送给我。到达后,我自己计算SHA1哈希,使用ASCII消息中的相同字段,然后尝试通过调用VerifyHash来验证这些字段是否未被更改。

密钥以两种形式提供:常规和“noNL”。 noNL版本包含在上面的代码中,常规版本是这样的:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVGUzbydMZS+fnkGTsUkDKEyFO
GwghR234d5GjPnMIC0RFtXtw2tdcNM8I9Qk+h6fnPHiA7r27iHBfdxTP3oegQJWp
bY2RMwSmOs02eQqpKx4QtIjWqkKk2Gmck5cll9GCoI8AUAA5e0D02T0ZgINDmo5y
GPhGAAmqYrm8YiupwQIDAQAB
-----END PUBLIC KEY-----
c# .net hash cryptography public-key-encryption
3个回答
14
投票

你的字符串是SubjectPublicKeyInfo的base64编码。你可以使用Bouncycastle.net解码它:

byte[] publicKeyBytes = Convert.FromBase64String(publicKeyString);
AsymmetricKeyParameter asymmetricKeyParameter = PublicKeyFactory.CreateKey(publicKeyBytes);
RsaKeyParameters rsaKeyParameters = (RsaKeyParameters) asymmetricKeyParameter;
RSAParameters rsaParameters = new RSAParameters();
rsaParameters.Modulus = rsaKeyParameters.Modulus.ToByteArrayUnsigned();
rsaParameters.Exponent = rsaKeyParameters.Exponent.ToByteArrayUnsigned();
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParameters);

4
投票

第一个base64只是一些二进制数据的编码。以二进制方式编码RSA公钥的方法不止一种。但是,如果你从OpenSSL得到它,它可能是DER编码的RSAPublicKey结构。

 RSAPublicKey ::= SEQUENCE {
     modulus            INTEGER,    -- n
     publicExponent     INTEGER  }  -- e

一般来说,你需要一个ASN.1解码器,Mono.Security.dll提供one,但是对于这样一个简单的结构你可能想手工完成,因为ASN.1基本上是一个Tag,Length和Value。


0
投票

如果您的合作伙伴也使用.NET,他/她可以从Mono的makecert https://github.com/mono/mono/blob/bf55818da11240bd108dc51b374fae3d3b5482ce/mcs/tools/security/makecert.cs派生出来生成证书文件并直接发送给您。

在这种情况下,您可以轻松加载证书而不是原始字节,

http://www.lextm.com/2012/02/simple-publicprivate-key-signing-sample-code/

© www.soinside.com 2019 - 2024. All rights reserved.