C# RSA 加密/解密带传输
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17128038/
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
C# RSA encryption/decryption with transmission
提问by Transmission
I've seen plenty of encryption/decryption tutorials and examples on the net in C# that use the System.Security.Cryptography.RSACryptoServiceProvider, but what I'm hoping to be able to do is:
我在 C# 网络上看到了大量使用 System.Security.Cryptography.RSACryptoServiceProvider 的加密/解密教程和示例,但我希望能够做的是:
- Create an RSA public/private keypair
- Transmit the public key (or for proof of concept, just move it in a string variable)
- Create a new RSA crypto provider and encrypt a string with the public key
- Transmit the encrypted string (or data) back to the original crypto provider and decrypt the string
- 创建 RSA 公钥/私钥对
- 传输公钥(或用于概念证明,只需将其移动到字符串变量中)
- 创建一个新的 RSA 加密提供程序并使用公钥加密一个字符串
- 将加密的字符串(或数据)传输回原始加密提供程序并解密字符串
Could anyone point me to a useful resource for this?
任何人都可以指出我对此有用的资源吗?
采纳答案by DarkSquirrel42
well there are really enough examples for this, but anyway, here you go
好吧,确实有足够的例子,但无论如何,你去吧
using System;
using System.Security.Cryptography;
namespace RsaCryptoExample
{
static class Program
{
static void Main()
{
//lets take a new CSP with a new 2048 bit rsa key pair
var csp = new RSACryptoServiceProvider(2048);
//how to get the private key
var privKey = csp.ExportParameters(true);
//and the public key ...
var pubKey = csp.ExportParameters(false);
//converting the public key into a string representation
string pubKeyString;
{
//we need some buffer
var sw = new System.IO.StringWriter();
//we need a serializer
var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters));
//serialize the key into the stream
xs.Serialize(sw, pubKey);
//get the string from the stream
pubKeyString = sw.ToString();
}
//converting it back
{
//get a stream from the string
var sr = new System.IO.StringReader(pubKeyString);
//we need a deserializer
var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters));
//get the object back from the stream
pubKey = (RSAParameters)xs.Deserialize(sr);
}
//conversion for the private key is no black magic either ... omitted
//we have a public key ... let's get a new csp and load that key
csp = new RSACryptoServiceProvider();
csp.ImportParameters(pubKey);
//we need some data to encrypt
var plainTextData = "foobar";
//for encryption, always handle bytes...
var bytesPlainTextData = System.Text.Encoding.Unicode.GetBytes(plainTextData);
//apply pkcs#1.5 padding and encrypt our data
var bytesCypherText = csp.Encrypt(bytesPlainTextData, false);
//we might want a string representation of our cypher text... base64 will do
var cypherText = Convert.ToBase64String(bytesCypherText);
/*
* some transmission / storage / retrieval
*
* and we want to decrypt our cypherText
*/
//first, get our bytes back from the base64 string ...
bytesCypherText = Convert.FromBase64String(cypherText);
//we want to decrypt, therefore we need a csp and load our private key
csp = new RSACryptoServiceProvider();
csp.ImportParameters(privKey);
//decrypt and strip pkcs#1.5 padding
bytesPlainTextData = csp.Decrypt(bytesCypherText, false);
//get our original plainText back...
plainTextData = System.Text.Encoding.Unicode.GetString(bytesPlainTextData);
}
}
}
as a side note: the calls to Encrypt() and Decrypt() have a bool parameter that switches between OAEP and PKCS#1.5 padding ... you might want to choose OAEP if it's available in your situation
作为旁注:对 Encrypt() 和 Decrypt() 的调用有一个 bool 参数,可以在 OAEP 和 PKCS#1.5 填充之间切换……如果在您的情况下可用,您可能想要选择 OAEP
回答by Mukund
public static string Encryption(string strText)
{
var publicKey = "<RSAKeyValue><Modulus>21wEnTU+mcD2w0Lfo1Gv4rtcSWsQJQTNa6gio05AOkV/Er9w3Y13Ddo5wGtjJ19402S71HUeN0vbKILLJdRSES5MHSdJPSVrOqdrll/vLXxDxWs/U0UT1c8u6k/Ogx9hTtZxYwoeYqdhDblof3E75d9n2F0Zvf6iTb4cI7j6fMs=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
var testData = Encoding.UTF8.GetBytes(strText);
using (var rsa = new RSACryptoServiceProvider(1024))
{
try
{
// client encrypting data with public key issued by server
rsa.FromXmlString(publicKey.ToString());
var encryptedData = rsa.Encrypt(testData, true);
var base64Encrypted = Convert.ToBase64String(encryptedData);
return base64Encrypted;
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
}
public static string Decryption(string strText)
{
var privateKey = "<RSAKeyValue><Modulus>21wEnTU+mcD2w0Lfo1Gv4rtcSWsQJQTNa6gio05AOkV/Er9w3Y13Ddo5wGtjJ19402S71HUeN0vbKILLJdRSES5MHSdJPSVrOqdrll/vLXxDxWs/U0UT1c8u6k/Ogx9hTtZxYwoeYqdhDblof3E75d9n2F0Zvf6iTb4cI7j6fMs=</Modulus><Exponent>AQAB</Exponent><P>/aULPE6jd5IkwtWXmReyMUhmI/nfwfkQSyl7tsg2PKdpcxk4mpPZUdEQhHQLvE84w2DhTyYkPHCtq/mMKE3MHw==</P><Q>3WV46X9Arg2l9cxb67KVlNVXyCqc/w+LWt/tbhLJvV2xCF/0rWKPsBJ9MC6cquaqNPxWWEav8RAVbmmGrJt51Q==</Q><DP>8TuZFgBMpBoQcGUoS2goB4st6aVq1FcG0hVgHhUI0GMAfYFNPmbDV3cY2IBt8Oj/uYJYhyhlaj5YTqmGTYbATQ==</DP><DQ>FIoVbZQgrAUYIHWVEYi/187zFd7eMct/Yi7kGBImJStMATrluDAspGkStCWe4zwDDmdam1XzfKnBUzz3AYxrAQ==</DQ><InverseQ>QPU3Tmt8nznSgYZ+5jUo9E0SfjiTu435ihANiHqqjasaUNvOHKumqzuBZ8NRtkUhS6dsOEb8A2ODvy7KswUxyA==</InverseQ><D>cgoRoAUpSVfHMdYXW9nA3dfX75dIamZnwPtFHq80ttagbIe4ToYYCcyUz5NElhiNQSESgS5uCgNWqWXt5PnPu4XmCXx6utco1UVH8HGLahzbAnSy6Cj3iUIQ7Gj+9gQ7PkC434HTtHazmxVgIR5l56ZjoQ8yGNCPZnsdYEmhJWk=</D></RSAKeyValue>";
var testData = Encoding.UTF8.GetBytes(strText);
using (var rsa = new RSACryptoServiceProvider(1024))
{
try
{
var base64Encrypted = strText;
// server decrypting data with private key
rsa.FromXmlString(privateKey);
var resultBytes = Convert.FromBase64String(base64Encrypted);
var decryptedBytes = rsa.Decrypt(resultBytes, true);
var decryptedData = Encoding.UTF8.GetString(decryptedBytes);
return decryptedData.ToString();
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
}
回答by CraftedGaming
Honestly, I have difficulty implementing it because there's barely any tutorials I've searched that displays writing the keys into the files. The accepted answer was "fine". But for me I had to improve it so that both keys gets saved into two separate files. I've written a helper class so y'all just gotta copy and paste it. Hope this helps lol.
老实说,我很难实现它,因为我搜索过的几乎没有任何教程显示将密钥写入文件。接受的答案是“很好”。但对我来说,我必须改进它,以便将两个键都保存到两个单独的文件中。我写了一个助手类,所以你们只需要复制并粘贴它。希望这有助于大声笑。
using Microsoft.Win32;
using System;
using System.IO;
using System.Security.Cryptography;
namespace RsaCryptoExample
{
class RSAFileHelper
{
readonly string pubKeyPath = "public.key";//change as needed
readonly string priKeyPath = "private.key";//change as needed
public void MakeKey()
{
//lets take a new CSP with a new 2048 bit rsa key pair
RSACryptoServiceProvider csp = new RSACryptoServiceProvider(2048);
//how to get the private key
RSAParameters privKey = csp.ExportParameters(true);
//and the public key ...
RSAParameters pubKey = csp.ExportParameters(false);
//converting the public key into a string representation
string pubKeyString;
{
//we need some buffer
var sw = new StringWriter();
//we need a serializer
var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters));
//serialize the key into the stream
xs.Serialize(sw, pubKey);
//get the string from the stream
pubKeyString = sw.ToString();
File.WriteAllText(pubKeyPath, pubKeyString);
}
string privKeyString;
{
//we need some buffer
var sw = new StringWriter();
//we need a serializer
var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters));
//serialize the key into the stream
xs.Serialize(sw, privKey);
//get the string from the stream
privKeyString = sw.ToString();
File.WriteAllText(priKeyPath, privKeyString);
}
}
public void EncryptFile(string filePath)
{
//converting the public key into a string representation
string pubKeyString;
{
using (StreamReader reader = new StreamReader(pubKeyPath)){pubKeyString = reader.ReadToEnd();}
}
//get a stream from the string
var sr = new StringReader(pubKeyString);
//we need a deserializer
var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters));
//get the object back from the stream
RSACryptoServiceProvider csp = new RSACryptoServiceProvider();
csp.ImportParameters((RSAParameters)xs.Deserialize(sr));
byte[] bytesPlainTextData = File.ReadAllBytes(filePath);
//apply pkcs#1.5 padding and encrypt our data
var bytesCipherText = csp.Encrypt(bytesPlainTextData, false);
//we might want a string representation of our cypher text... base64 will do
string encryptedText = Convert.ToBase64String(bytesCipherText);
File.WriteAllText(filePath,encryptedText);
}
public void DecryptFile(string filePath)
{
//we want to decrypt, therefore we need a csp and load our private key
RSACryptoServiceProvider csp = new RSACryptoServiceProvider();
string privKeyString;
{
privKeyString = File.ReadAllText(priKeyPath);
//get a stream from the string
var sr = new StringReader(privKeyString);
//we need a deserializer
var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters));
//get the object back from the stream
RSAParameters privKey = (RSAParameters)xs.Deserialize(sr);
csp.ImportParameters(privKey);
}
string encryptedText;
using (StreamReader reader = new StreamReader(filePath)) { encryptedText = reader.ReadToEnd(); }
byte[] bytesCipherText = Convert.FromBase64String(encryptedText);
//decrypt and strip pkcs#1.5 padding
byte[] bytesPlainTextData = csp.Decrypt(bytesCipherText, false);
//get our original plainText back...
File.WriteAllBytes(filePath, bytesPlainTextData);
}
}
}
回答by Tigran
I'll share my very simple code for sample purpose. Hope it will help someone like me searching for quick code reference. My goal was to receive rsa signature from backend, then validate against input string using public key and store locally for future periodic verifications. Here is main part used for signature verification:
出于示例目的,我将分享我的非常简单的代码。希望它能帮助像我这样搜索快速代码参考的人。我的目标是从后端接收 rsa 签名,然后使用公钥验证输入字符串并在本地存储以备将来定期验证。这是用于签名验证的主要部分:
...
var signature = Get(url); // base64_encoded signature received from server
var inputtext= "inputtext"; // this is main text signature was created for
bool result = VerifySignature(inputtext, signature);
...
private bool VerifySignature(string input, string signature)
{
var result = false;
using (var cps=new RSACryptoServiceProvider())
{
// converting input and signature to Bytes Arrays to pass to VerifyData rsa method to verify inputtext was signed using privatekey corresponding to public key we have below
byte[] inputtextBytes = Encoding.UTF8.GetBytes(input);
byte[] signatureBytes = Convert.FromBase64String(signature);
cps.FromXmlString("<RSAKeyValue><Modulus>....</Modulus><Exponent>....</Exponent></RSAKeyValue>"); // xml formatted publickey
result = cps.VerifyData(inputtextBytes , new SHA1CryptoServiceProvider(), signatureBytes );
}
return result;
}

