C# RSA 加密/解密与传输
Posted
技术标签:
【中文标题】C# RSA 加密/解密与传输【英文标题】:C# RSA encryption/decryption with transmission 【发布时间】:2013-06-12 06:10:02 【问题描述】:我在网上看到了大量使用 System.Security.Cryptography.RSACryptoServiceProvider 的 C# 加密/解密教程和示例,但我希望能够做到的是:
创建 RSA 公钥/私钥对 传输公钥(或者为了概念验证,只需将其移动到字符串变量中) 创建新的 RSA 加密提供程序并使用公钥加密字符串 将加密的字符串(或数据)传输回原始加密提供者并解密该字符串谁能给我指出一个有用的资源?
【问题讨论】:
您能否指出一个具体的教程来解释在 C# 中使用 RSA 进行加密和解密,但不能满足您的特定需求?我想说它们非常简单,从你的问题中我不清楚你在哪一部分有问题。 同样在第 1 点上,将私钥存储在机器上的本地存储/容器中的最佳做法是,数据最终会被解密。 【参考方案1】:确实有足够多的例子,但无论如何,给你
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);
附带说明:对 Encrypt() 和 Decrypt() 的调用有一个 bool 参数,可在 OAEP 和 PKCS#1.5 填充之间切换……如果您的情况可用,您可能希望选择 OAEP
【讨论】:
非常感谢您,先生!我会支持你,但我需要 15 个代表。当我这样做时,我会记住你的! :) @Transmission:如果回答了您的问题,请考虑接受meta.stackexchange.com/a/5235/161449 这样 cypherText 会变得很长!是否有任何算法可以在具有相同安全性的同时缩短它? (最好只包含数字和大写字母) @SepehrM RSA 并非旨在加密大量数据......您可能应该考虑使用 AES 或 Twofish 等对称密码来加密数据,并使用 RSA(或其他不对称密码)来加密你的对称密钥......混合加密...... @DarkSquirrel42 顺便说一句,WannaCry 就是这样快速加密文件的。【参考方案2】: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;
【讨论】:
你是如何生成密钥的 @Sana 您可以使用ToXmlString
方法获取密钥。检查this answer。【参考方案3】:
老实说,我很难实现它,因为我搜索过的教程几乎没有显示将密钥写入文件。接受的答案是“很好”。但对我来说,我必须改进它,以便将两个密钥保存到两个单独的文件中。我写了一个助手类,所以你们都必须复制并粘贴它。希望这有助于大声笑。
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);
【讨论】:
为什么要使用 XmlSerializer?【参考方案4】:我将分享我非常简单的代码用于示例目的。希望它能帮助像我这样的人搜索快速代码参考。 我的目标是从后端接收 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;
【讨论】:
以上是关于C# RSA 加密/解密与传输的主要内容,如果未能解决你的问题,请参考以下文章