C# 使用 Base64 编码的公钥来验证 RSA 签名
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9283716/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Base64 encoded Public Key to verify RSA signature
提问by jscheppers
In a nutshell, this is my problem:
简而言之,这是我的问题:
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);
As you can see, the problem is initiating a new RSACryptoServiceProvider with the given Base64 encoded public key string. I've been able to do the instantiation using an object RSAParameters, loaded with the byte[]'s for Modulus and Exponent derived from this public key string using an OpenSSL shell command. But since this public key may change in the future I want to be able to store it in its original form in a database. There must be a more straightforward way of dealing with this.
如您所见,问题在于使用给定的 Base64 编码公钥字符串启动新的 RSACryptoServiceProvider。我已经能够使用对象 RSAParameters 进行实例化,使用 OpenSSL shell 命令从这个公钥字符串中加载字节 [] 的模数和指数。但是由于这个公钥将来可能会改变,我希望能够将它以原始形式存储在数据库中。必须有更直接的方法来处理这个问题。
A lot of the examples I've read so far avoid this problem by exporting and importing the generated private and public keys to and from a key-container object and use it in the same piece of code and thus not 'transferring' the key in some string form out of memory. Some people have expressed the same problem, both here on StackOverflow and on other sites, but I have not been able to find a satisfying answer yet.
到目前为止,我读过的许多示例都通过将生成的私钥和公钥导出到密钥容器对象和从密钥容器对象导入并在同一段代码中使用它来避免这个问题,因此不会“传输”密钥内存不足的一些字符串形式。有些人在 StackOverflow 和其他网站上都表达了同样的问题,但我还没有找到令人满意的答案。
Any idea's are more than welcome.
任何想法都非常受欢迎。
Background info: My communication partner computes a 20-byte SHA1-hash from an input string of variable length, composed of the information contained in several fields of an ASCII encoded message. This hash is then RSA-signed with my partner's private key and sent along with the ASCII message to me. Upon arrival, I compute the SHA1 hash myself, using the same fields from the ASCII message and then try to verify if these fields were not altered by calling VerifyHash.
背景信息:我的通信伙伴根据可变长度的输入字符串计算 20 字节的 SHA1 哈希,该字符串由包含在 ASCII 编码消息的多个字段中的信息组成。这个散列然后用我伙伴的私钥进行 RSA 签名,并与 ASCII 消息一起发送给我。到达后,我自己计算 SHA1 哈希,使用来自 ASCII 消息的相同字段,然后尝试通过调用 VerifyHash 来验证这些字段是否未更改。
The key is provided in 2 forms: regular and 'noNL'. The noNL version is included in the code above, the regular version is this:
密钥以两种形式提供:常规和“noNL”。上面的代码中包含了 noNL 版本,常规版本是这样的:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVGUzbydMZS+fnkGTsUkDKEyFO
GwghR234d5GjPnMIC0RFtXtw2tdcNM8I9Qk+h6fnPHiA7r27iHBfdxTP3oegQJWp
bY2RMwSmOs02eQqpKx4QtIjWqkKk2Gmck5cll9GCoI8AUAA5e0D02T0ZgINDmo5y
GPhGAAmqYrm8YiupwQIDAQAB
-----END PUBLIC KEY-----
采纳答案by Rasmus Faber
Your string is the base64 encoding of a SubjectPublicKeyInfo. You can use Bouncycastle.netto decode it like this:
您的字符串是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);
回答by poupou
First base64is only an encoding of some binary data. There's more than one way to encode, in binary, an RSA public key. However if you got this from OpenSSL it's likely a DER-encoded RSAPublicKeystructure.
首先base64只是一些二进制数据的编码。以二进制形式对 RSA 公钥进行编码的方法不止一种。但是,如果您是从 OpenSSL 获得的,它很可能是一个 DER 编码的RSAPublicKey结构。
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER } -- e
In general you would need a ASN.1 decoder, Mono.Security.dllprovides one, but for such a simple structure you might want to do it by handsince ASN.1 is basically a Tag, Lengthand a Value.
一般来说,您需要一个 ASN.1 解码器,Mono.Security.dll提供了一个,但对于这样一个简单的结构,您可能想要手动完成,因为 ASN.1 基本上是一个Tag、Length和一个Value。
回答by Lex Li
If your partner also uses .NET, he/she can derive from Mono's makecert https://github.com/mono/mono/blob/bf55818da11240bd108dc51b374fae3d3b5482ce/mcs/tools/security/makecert.csto generate certificate files and send to you directly.
如果你的伙伴也使用.NET,他/她可以从Mono的makecert派生https://github.com/mono/mono/blob/bf55818da11240bd108dc51b374fae3d3b5482ce/mcs/tools/security/makecert.cs生成证书文件,直接发给你.
In that case, you can easily load certificates instead of raw bytes,
在这种情况下,您可以轻松加载证书而不是原始字节,
http://www.lextm.com/2012/02/simple-publicprivate-key-signing-sample-code/
http://www.lextm.com/2012/02/simple-publicprivate-key-signing-sample-code/

![C# 如何[分组依据]数据表并将结果放入另一个数据表?](/res/img/loading.gif)