RSA介绍
RSA公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。
RSA的缺点:
- 产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密。
- 分组长度太大,为保证安全性,n 至少也要 600bits以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。目前,SET(Secure Electronic Transaction)协议中要求CA采用2048bits长的密钥,其他实体使用1024比特的密钥。C)RSA密钥长度随着保密级别提高,增加很快。下表列出了对同一安全级别所对应的密钥长度。
保密级别 |
对称密钥长度(bit) |
RSA密钥长度(bit) |
ECC密钥长度(bit) |
保密年限 |
80 |
80 |
1024 |
160 |
2010 |
112 |
112 |
2048 |
224 |
2030 |
128 |
128 |
3072 |
256 |
2040 |
192 |
192 |
7680 |
384 |
2080 |
256 |
256 |
15360 |
512 |
2120 |
RSA的参数
RSA密码由三个整数组成,我们分别称之为n, e, d
(n、d): 私钥,这个我们要私密保存
(n、e): 公钥,可以对外公布
n: 模数(Modulus),私钥和公钥都包含有这个数
e: 公钥指数(publicExponent),一般是固定值65537
d:私钥指数(privateExponent)
dotnet中的表示RSA参数的结构体是RSAParameters
openssl生成RSA密钥对
1. 生成一个RSA密钥
openssl genrsa -out private_pkcs1.pem 2048
上面的命令导出是pkcs#1
格式rsa私钥
2. 从生成的RSA密钥中提取RSA公钥
ps: 私钥中包含了公钥相关信息,所以可以从私钥中导出公钥信息
openssl rsa -in private_pkcs1.pem -out public_pkcs1.pem -pubout -RSAPublicKey_out
公钥格式转换(PKCS#8 => PKCS#1)
openssl rsa -in public_pkcs8.pem -out public_pkcs1.pem -pubin -RSAPublicKey_out
私钥格式转换 (PKCS#1 => PKCS#8)
openssl pkcs8 -in private_pkcs1.pem -out private_pkcs8.pem -topk8 -nocrypt
RSA私钥格式转换(PKCS#8 => PKCS#1)
openssl rsa -in private_pkcs8.pem -out private_pkcs1.pem
C#中RSA的相关操作
生成公钥和私钥
struct RSASecretKey
{
public RSASecretKey(string privateKey, string publicKey)
{
PrivateKey = privateKey;
PublicKey = publicKey;
}
public string PublicKey { get; set; }
public string PrivateKey { get; set; }
public override string ToString()
{
return string.Format(
"PrivateKey: {0}\r\nPublicKey: {1}", PrivateKey, PublicKey);
}
}
/// <summary>
/// generate RSA secret key
/// </summary>
/// <param name="keySize">the size of the key,must from 384 bits to 16384 bits in increments of 8 </param>
/// <returns></returns>
RSASecretKey GenerateRSASecretKey(int keySize)
{
RSASecretKey rsaKey = new RSASecretKey();
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(keySize))
{
rsaKey.PrivateKey = rsa.ToXmlString(true);
rsaKey.PublicKey = rsa.ToXmlString(false);
}
return rsaKey;
}
实现公钥加密私钥解密
string RSAEncrypt(string xmlPublicKey,string content)
{
string encryptedContent = string.Empty;
using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(xmlPublicKey);
byte[] encryptedData = rsa.Encrypt(Encoding.Default.GetBytes(content), false);
encryptedContent = Convert.ToBase64String(encryptedData);
}
return encryptedContent;
}
string RSADecrypt(string xmlPrivateKey, string content)
{
string decryptedContent = string.Empty;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(xmlPrivateKey);
byte[] decryptedData = rsa.Decrypt(Convert.FromBase64String(content), false);
decryptedContent = Encoding.GetEncoding("gb2312").GetString(decryptedData);
}
return decryptedContent;
}
密钥格式的转换
C#中RSA公钥和私钥的格式都是XML的,而在其他语言如java中,生成的RSA密钥就是普通的Base64字符串,所以需要将C#xml格式的密钥转换成普通的Base64字符串,同时也要实现Base64密钥字符串生成C#中xml格式的密钥.
安装 BouncyCastle 这个Nuget包PM > Install-Package BouncyCastle
BouncyCastle项目网址BouncyCastlegithub地址 构造一个RSAKeyConventer类
namespace RSA
{
using System;
using System.Security.Cryptography;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Parameters;
public class RSAKeyConverter
{
/// <summary>
/// xml private key -> base64 private key string
/// </summary>
/// <param name="xmlPrivateKey"></param>
/// <returns></returns>
public static string FromXmlPrivateKey(string xmlPrivateKey)
{
string result = string.Empty;
using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(xmlPrivateKey);
RSAParameters param = rsa.ExportParameters(true);
RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(
new BigInteger(1, param.Modulus), new BigInteger(1, param.Exponent),
new BigInteger(1, param.D), new BigInteger(1, param.P),
new BigInteger(1, param.Q), new BigInteger(1, param.DP),
new BigInteger(1, param.DQ), new BigInteger(1, param.InverseQ));
PrivateKeyInfo privateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
result = Convert.ToBase64String(privateKey.ToAsn1Object().GetEncoded());
}
return result;
}
/// <summary>
/// xml public key -> base64 public key string
/// </summary>
/// <param name="xmlPublicKey"></param>
/// <returns></returns>
public static string FromXmlPublicKey(string xmlPublicKey)
{
string result = string.Empty;
using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(xmlPublicKey);
RSAParameters p = rsa.ExportParameters(false);
RsaKeyParameters keyParams = new RsaKeyParameters(
false, new BigInteger(1,p.Modulus), new BigInteger(1, p.Exponent));
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyParams);
result = Convert.ToBase64String(publicKeyInfo.ToAsn1Object().GetEncoded());
}
return result;
}
/// <summary>
/// base64 private key string -> xml private key
/// </summary>
/// <param name="privateKey"></param>
/// <returns></returns>
public static string ToXmlPrivateKey(string privateKey)
{
RsaPrivateCrtKeyParameters privateKeyParams =
PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey)) as RsaPrivateCrtKeyParameters;
using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
RSAParameters rsaParams = new RSAParameters()
{
Modulus = privateKeyParams.Modulus.ToByteArrayUnsigned(),
Exponent = privateKeyParams.PublicExponent.ToByteArrayUnsigned(),
D = privateKeyParams.Exponent.ToByteArrayUnsigned(),
DP = privateKeyParams.DP.ToByteArrayUnsigned(),
DQ = privateKeyParams.DQ.ToByteArrayUnsigned(),
P = privateKeyParams.P.ToByteArrayUnsigned(),
Q = privateKeyParams.Q.ToByteArrayUnsigned(),
InverseQ = privateKeyParams.QInv.ToByteArrayUnsigned()
};
rsa.ImportParameters(rsaParams);
return rsa.ToXmlString(true);
}
}
/// <summary>
/// base64 public key string -> xml public key
/// </summary>
/// <param name="pubilcKey"></param>
/// <returns></returns>
public static string ToXmlPublicKey(string pubilcKey)
{
RsaKeyParameters p =
PublicKeyFactory.CreateKey(Convert.FromBase64String(pubilcKey)) as RsaKeyParameters;
using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
RSAParameters rsaParams = new RSAParameters
{
Modulus = p.Modulus.ToByteArrayUnsigned(),
Exponent = p.Exponent.ToByteArrayUnsigned()
};
rsa.ImportParameters(rsaParams);
return rsa.ToXmlString(false);
}
}
}
}
C# 折叠 复制 全屏
js的rsa操作
移步: GitHub - travist/jsencrypt: A zero-dependency Javascript library to perform OpenSSL RSA Encryption, Decryption, and Key Generation.
作者:Laggage