我在Java中有以下代码示例,我需要在C#中重新编写它:
PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(pkcs8PrivateKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privKey = keyFactory.generatePrivate(privKeySpec);
Signature sign = Signature.getInstance("MD5withRSA");
sign.initSign(privKey);
sign.update(data);
byte[] signature = sign.sign();
是否可以使用标准的.Net Crypto API,还是应该使用BouncyCastle? 谢谢,
湾
答案 0 :(得分:9)
另一种方法是使用CNG(下一代加密)以及来自CodePlex的Security.Cryptography DLL
然后你可以写:
byte[] dataToSign = Encoding.UTF8.GetBytes("Data to sign");
using (CngKey signingKey = CngKey.Import(pkcs8PrivateKey, CngKeyBlobFormat.Pkcs8PrivateBlob))
using (RSACng rsa = new RSACng(signingKey))
{
rsa.SignatureHashAlgorithm = CngAlgorithm.MD5;
return rsa.SignData(dataToSign);
}
感谢Simon Mourier:使用.Net 4.6,您不再需要单独的库
答案 1 :(得分:3)
我遇到了一个非常类似的问题,试图创建一个用于打包Chrome扩展的原生C#工具(使用SHA1,而不是MD5,但这没有太大区别)。我相信我已经尝试过.Net的每个可能的解决方案:System.Security.Cryptography,BouncyCastle,OpenSSL.Net和Chilkat RSA。
最好的解决方案可能是奇尔卡特;他们的界面是最干净,最直接的,它得到了良好的支持和良好的记录,并且有一百万个例子。例如,这里有一些代码使用他们的库来完成你想要的东西:http://www.example-code.com/csharp/rsa_signPkcs8.asp。然而,它不是免费的(虽然150美元并非不合理,因为我已经烧了2天试图解决这个问题,而且我每天花费超过75美元!)。
作为一种免费的替代方案,JavaScience在http://www.jensign.com/JavaScience/cryptoutils/index.html为多种语言(包括C#/ .Net)提供了许多源代码形式的加密实用程序。对于您要做的事情最突出的是opensslkey(http://www.jensign.com/opensslkey/index.html),它将允许您从.pem文件生成RSACryptoServiceProvider。然后,您可以使用该提供程序对代码进行签名:
string pemContents = new StreamReader("pkcs8privatekey.pem").ReadToEnd();
var der = opensslkey.DecodePkcs8PrivateKey(pemContents);
RSACryptoServiceProvider rsa = opensslkey.DecodePrivateKeyInfo(der);
signature = rsa.SignData(data, new MD5CryptoServiceProvider());
答案 2 :(得分:1)
This SO question回答了代码的PKCS#8部分。其余的.NET RSA类是一个奇怪的混乱的部分重叠类,很难理解。肯定看来,签名支持位于RSACryptoServiceProvider和/或RSAPKCS1SignatureFormatter类中。
答案 3 :(得分:1)
免责声明:我了解Java和加密技术,但我对C#和.NET的了解非常有限。我只是在Google-fu技能的影响下在这里写作。
假设您可以解码PKCS#8编码的RSA私钥,那么,根据我在MSDN上阅读的内容,其余代码应该如下所示:
byte[] hv = MD5.Create().ComputeHash(data);
RSACryptoServiceProvider rsp = new RSACryptoServiceProvider();
RSAParameters rsp = new RSAParameters();
// here fill rsp fields by decoding pkcs8PrivateKey
rsp.ImportParameters(key);
RSAPKCS1SignatureFormatter rf = new RSAPKCS1SignatureFormatter(rsp);
rf.SetHashAlgorithm("MD5");
byte[] signature = rf.CreateSignature(hv);
相关的类位于System.Security.Cryptography
命名空间中。
对于PKCS#8密钥blob解码(即填入rsp
字段),我发现this page描述了C#中可以执行该作业的命令行实用程序。提供源代码并且是单个C#文件。根据我在其中读到的内容,该代码“手动”解码PKCS#8文件;间接地,这应该意味着原始.NET(2.0)没有用于PKCS#8密钥文件解码的工具(否则该工具的作者将不会遇到实现这种解码的麻烦)。对于您手头的任务,您可以从源文件中清除所需的部分,跳过有关PEM和对称加密的任何内容;你的入口点是DecodePrivateKeyInfo()
函数,它显然需要一个DER编码的未加密的PKCS#8文件,就像Java的PKCS8EncodedKeySpec
一样。
答案 4 :(得分:0)
您可以使用此代码。首先你应该下载" BouncyCastle.Crypto.dll"来自http://www.bouncycastle.org/csharp/。
/// <summary>
/// MD5withRSA Signing
/// https://www.vrast.cn
/// keyle_xiao 2017.1.12
/// </summary>
public class MD5withRSASigning
{
public Encoding encoding = Encoding.UTF8;
public string SignerSymbol = "MD5withRSA";
public MD5withRSASigning() { }
public MD5withRSASigning(Encoding e, string s)
{
encoding = e;
SignerSymbol = s;
}
private AsymmetricKeyParameter CreateKEY(bool isPrivate, string key)
{
byte[] keyInfoByte = Convert.FromBase64String(key);
if (isPrivate)
return PrivateKeyFactory.CreateKey(keyInfoByte);
else
return PublicKeyFactory.CreateKey(keyInfoByte);
}
public string Sign(string content, string privatekey)
{
ISigner sig = SignerUtilities.GetSigner(SignerSymbol);
sig.Init(true, CreateKEY(true, privatekey));
var bytes = encoding.GetBytes(content);
sig.BlockUpdate(bytes, 0, bytes.Length);
byte[] signature = sig.GenerateSignature();
/* Base 64 encode the sig so its 8-bit clean */
var signedString = Convert.ToBase64String(signature);
return signedString;
}
public bool Verify(string content, string signData, string publickey)
{
ISigner signer = SignerUtilities.GetSigner(SignerSymbol);
signer.Init(false, CreateKEY(false, publickey));
var expectedSig = Convert.FromBase64String(signData);
/* Get the bytes to be signed from the string */
var msgBytes = encoding.GetBytes(content);
/* Calculate the signature and see if it matches */
signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
return signer.VerifySignature(expectedSig);
}
}