rsa加密算法_.NET Core加解密实战系列之——RSA非对称加密算法

611a50ab66ac584d24683af4cd9be4a7.png

简介

加解密现状,编写此项目的背景:

  • 需要考虑系统环境兼容性问题(Linux、Windows)

  • 语言互通问题(如C#、Java)

  • 网上资料版本不一、不全面

  • .NET官方库密码算法提供不全面,很难针对其他语言(Java)进行适配

本系列文章主要介绍如何结合BouncyCastle在 .NET Core 中使用非对称加密算法、编码算法、哈希算法、对称加密算法、国密算法等一系列算法,内容篇幅代码居多(加解密算法相关的原理知识网上有很多,因此不过多介绍)。如有错误之处,还请大家批评指正。

本系列代码项目地址:https://github.com/fuluteam/ICH.BouncyCastle.git

功能依赖

BouncyCastle(https://www.bouncycastle.org/csharp) 是一个开放源码的轻量级密码术包;它支持大量的密码术算法,它提供了很多.NET Core标准库没有的算法。

支持.NET 4,.NET Standard 1.0-2.0,WP,Silverlight,MonoAndroid,Xamarin.iOS,.NET Core

功能依赖
Portable.BouncyCastlePortable.BouncyCastle • 1.8.5

生成RSA秘钥

PKCS1格式

///

/// PKCS1(非Java适用)

///

/// 密钥长度”一般只是指模值的位长度。目前主流可选值:1024、2048、3072、4096...

/// PEM格式

///

public RSAKeyParameter Pkcs1(int keySize, bool format=false)

{

var keyGenerator = GeneratorUtilities.GetKeyPairGenerator("RSA");

keyGenerator.Init(new KeyGenerationParameters(new SecureRandom(), keySize));

var keyPair = keyGenerator.GenerateKeyPair();

var subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public);

var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private);

if (!format)

{

return new RSAKeyParameter

{

PrivateKey = Base64.ToBase64String(privateKeyInfo.ParsePrivateKey().GetEncoded()),

PublicKey = Base64.ToBase64String(subjectPublicKeyInfo.GetEncoded())

};

}

var rsaKey = new RSAKeyParameter();

using (var sw = new StringWriter())

{

var pWrt = new PemWriter(sw);

pWrt.WriteObject(keyPair.Private);

pWrt.Writer.Close();

rsaKey.PrivateKey = sw.ToString();

}

using (var sw = new StringWriter())

{

var pWrt = new PemWriter(sw);

pWrt.WriteObject(keyPair.Public);

pWrt.Writer.Close();

rsaKey.PublicKey = sw.ToString();

}

return rsaKey;

}

PKCS8格式

///

/// PKCS8(JAVA适用)

///

/// 密钥长度”一般只是指模值的位长度。目前主流可选值:1024、2048、3072、4096...

/// PEM格式

///

public RSAKeyParameter Pkcs8(int keySize, bool format=false)

{

var keyGenerator = GeneratorUtilities.GetKeyPairGenerator("RSA");

keyGenerator.Init(new KeyGenerationParameters(new SecureRandom(), keySize));

var keyPair = keyGenerator.GenerateKeyPair();

var subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public);

var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private);

if (!format)

{

return new RSAKeyParameter

{

PrivateKey = Base64.ToBase64String(privateKeyInfo.GetEncoded()),

PublicKey = Base64.ToBase64String(subjectPublicKeyInfo.GetEncoded())

};

}

var rsaKey = new RSAKeyParameter();

using (var sw = new StringWriter())

{

var pWrt = new PemWriter(sw);

var pkcs8 = new Pkcs8Generator(keyPair.Private);

pWrt.WriteObject(pkcs8);

pWrt.Writer.Close();

rsaKey.PrivateKey = sw.ToString();

}

using (var sw = new StringWriter())

{

var pWrt = new PemWriter(sw);

pWrt.WriteObject(keyPair.Public);

pWrt.Writer.Close();

rsaKey.PublicKey = sw.ToString();

}

return rsaKey;

}

私钥操作

PKCS1与PKCS8格式互转

仅私钥有PKCS1和PKCS8之分,公钥无格式区别。

///

/// Pkcs1>>Pkcs8

///

/// Pkcs1私钥

/// 是否转PEM格式

///

public static string PrivateKeyPkcs1ToPkcs8(string privateKey, bool format = false)

{

var akp = RSAUtilities.GetAsymmetricKeyParameterFormPrivateKey(privateKey);

if (format)

{

var sw = new StringWriter();

var pWrt = new PemWriter(sw);

var pkcs8 = new Pkcs8Generator(akp);

pWrt.WriteObject(pkcs8);

pWrt.Writer.Close();

return sw.ToString();

}

else

{

var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(akp);

return Base64.ToBase64String(privateKeyInfo.GetEncoded());

}

}

///

/// Pkcs8>>Pkcs1

///

/// Pkcs8私钥

/// 是否转PEM格式

///

public static string PrivateKeyPkcs8ToPkcs1(string privateKey, bool format = false)

{

var akp = RSAUtilities.GetAsymmetricKeyParameterFormAsn1PrivateKey(privateKey);

if (format)

{

var sw = new StringWriter();

var pWrt = new PemWriter(sw);

pWrt.WriteObject(akp);

pWrt.Writer.Close();

return sw.ToString();

}

else

{

var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(akp);

return Base64.ToBase64String(privateKeyInfo.ParsePrivateKey().GetEncoded());

}

}

PKCS1与PKCS8私钥中提取公钥

///

/// 从Pkcs1私钥中提取公钥

///

/// Pkcs1私钥

///

public static string GetPublicKeyFromPrivateKeyPkcs1(string privateKey)

{

var instance = RsaPrivateKeyStructure.GetInstance(Base64.Decode(privateKey));

var publicParameter = (AsymmetricKeyParameter)new RsaKeyParameters(false, instance.Modulus,instance.PublicExponent);

var privateParameter = (AsymmetricKeyParameter)new RsaPrivateCrtKeyParameters(instance.Modulus,instance.PublicExponent, instance.PrivateExponent, instance.Prime1, instance.Prime2, instance.Exponent1,instance.Exponent2, instance.Coefficient);

var keyPair = new AsymmetricCipherKeyPair(publicParameter, privateParameter);

var subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public);

return Base64.ToBase64String(subjectPublicKeyInfo.GetEncoded());

}

///

/// 从Pkcs8私钥中提取公钥

///

/// Pkcs8私钥

///

public static string GetPublicKeyFromPrivateKeyPkcs8(string privateKey)

{

var privateKeyInfo = PrivateKeyInfo.GetInstance(Asn1Object.FromByteArray(Base64.Decode(privateKey)));

privateKey = Base64.ToBase64String(privateKeyInfo.ParsePrivateKey().GetEncoded());

var instance = RsaPrivateKeyStructure.GetInstance(Base64.Decode(privateKey));

var publicParameter = (AsymmetricKeyParameter)new RsaKeyParameters(false, instance.Modulus,instance.PublicExponent);

var privateParameter = (AsymmetricKeyParameter)new RsaPrivateCrtKeyParameters(instance.Modulus,instance.PublicExponent, instance.PrivateExponent, instance.Prime1, instance.Prime2, instance.Exponent1,instance.Exponent2, instance.Coefficient);

var keyPair = new AsymmetricCipherKeyPair(publicParameter, privateParameter);

var subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public);

return Base64.ToBase64String(subjectPublicKeyInfo.GetEncoded());

}

PEM操作

PEM格式密钥读取

public static string ReadPkcs1PrivateKey(string text)

{

if (!text.StartsWith("-----BEGIN RSA PRIVATE KEY-----"))

{

return text;

}

using (var reader = new StringReader(text))

{

var pr = new PemReader(reader);

var keyPair = pr.ReadObject() as AsymmetricCipherKeyPair;

pr.Reader.Close();

var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair?.Private);

return Base64.ToBase64String(privateKeyInfo.ParsePrivateKey().GetEncoded());

}

}

public static string ReadPkcs8PrivateKey(string text)

{

if (!text.StartsWith("-----BEGIN PRIVATE KEY-----"))

{

return text;

}

using (var reader = new StringReader(text))

{

var pr = new PemReader(reader);

var akp = pr.ReadObject() as AsymmetricKeyParameter; ;

pr.Reader.Close();

return Base64.ToBase64String(PrivateKeyInfoFactory.CreatePrivateKeyInfo(akp).GetEncoded());

}

}

public static string ReadPublicKey(string text)

{

if (!text.StartsWith("-----BEGIN PUBLIC KEY-----"))

{

return text;

}

using (var reader = new StringReader(text))

{

var pr = new PemReader(reader);

var keyPair = pr.ReadObject() as AsymmetricCipherKeyPair;

pr.Reader.Close();

var subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair?.Public);

returnBase64.ToBase64String(subjectPublicKeyIno.GetEncoded());

}

}

PEM格式密钥写入

public static string WritePkcs1PrivateKey(string privateKey)

{

if (privateKey.StartsWith("-----BEGIN RSA PRIVATE KEY-----"))

{

return privateKey;

}

var akp = RSAUtilities.GetAsymmetricKeyParameterFormPrivateKey(privateKey);

using (var sw = new StringWriter())

{

var pWrt = new PemWriter(sw);

pWrt.WriteObject(akp);

pWrt.Writer.Close();

return sw.ToString();

}

}

public static string WritePkcs8PrivateKey(string privateKey)

{

if (privateKey.StartsWith("-----BEGIN PRIVATE KEY-----"))

{

return privateKey;

}

var akp = RSAUtilities.GetAsymmetricKeyParameterFormAsn1PrivateKey(privateKey);

using (var sw = new StringWriter())

{

var pWrt = new PemWriter(sw);

var pkcs8 = new Pkcs8Generator(akp);

pWrt.WriteObject(pkcs8);

pWrt.Writer.Close();

return sw.ToString();

}

}

public static string WritePublicKey(string publicKey)

{

if (publicKey.StartsWith("-----BEGIN PUBLIC KEY-----"))

{

return publicKey;

}

var akp = RSAUtilities.GetAsymmetricKeyParameterFormPublicKey(publicKey);

using (var sw = new StringWriter())

{

var pWrt = new PemWriter(sw);

pWrt.WriteObject(akp);

pWrt.Writer.Close();

return sw.ToString();

}

}

RSA加解密

获取非对称秘钥参数(AsymmetricKeyParameter)

///

/// -----BEGIN RSA PRIVATE KEY-----

/// ...

/// -----END RSA PRIVATE KEY-----

///

/// Pkcs1格式私钥

///

public static AsymmetricKeyParameter GetAsymmetricKeyParameterFormPrivateKey(string privateKey)

{

if (string.IsNullOrEmpty(privateKey))

{

throw new ArgumentNullException(nameof(privateKey));

}

var instance = RsaPrivateKeyStructure.GetInstance(Base64.Decode(privateKey));

return new RsaPrivateCrtKeyParameters(instance.Modulus, instance.PublicExponent, instance.PrivateExponent,instance.Prime1, instance.Prime2, instance.Exponent1, instance.Exponent2, instance.Coefficient);

}

///

/// -----BEGIN PRIVATE KEY-----

/// ...

/// -----END PRIVATE KEY-----

///

/// Pkcs8格式私钥

///

public static AsymmetricKeyParameter GetAsymmetricKeyParameterFormAsn1PrivateKey(string privateKey)

{

return PrivateKeyFactory.CreateKey(Base64.Decode(privateKey));

}

///

/// -----BEGIN PUBLIC KEY-----

/// ...

/// -----END PUBLIC KEY-----

///

/// 公钥

///

public static AsymmetricKeyParameter GetAsymmetricKeyParameterFormPublicKey(string publicKey)

{

if (string.IsNullOrEmpty(publicKey))

{

throw new ArgumentNullException(nameof(publicKey));

}

return PublicKeyFactory.CreateKey(Base64.Decode(publicKey));

}

RSA加解与解密

///

/// RSA加密

///

/// 未加密数据字节数组

/// 非对称密钥参数

/// 密文算法

/// 已加密数据字节数组

public static byte[] Encrypt(byte[] data, AsymmetricKeyParameter parameters, string algorithm)

{

if (data == null)

{

throw new ArgumentNullException(nameof(data));

}

if (parameters == null)

{

throw new ArgumentNullException(nameof(parameters));

}

if (string.IsNullOrEmpty(algorithm))

{

throw new ArgumentNullException(nameof(algorithm));

}

var bufferedCipher = CipherUtilities.GetCipher(algorithm);

bufferedCipher.Init(true, parameters);

return bufferedCipher.DoFinal(data);

}

///

/// RSA解密

///

/// 已加密数据字节数组

/// 非对称密钥参数

/// 密文算法

/// 未加密数据字节数组

public static byte[] Decrypt(byte[] data, AsymmetricKeyParameter parameters, string algorithm)

{

if (data == null)

{

throw new ArgumentNullException(nameof(data));

}

if (parameters == null)

{

throw new ArgumentNullException(nameof(parameters));

}

if (string.IsNullOrEmpty(algorithm))

{

throw new ArgumentNullException(nameof(algorithm));

}

var bufferedCipher = CipherUtilities.GetCipher(algorithm);

bufferedCipher.Init(false, parameters);

return bufferedCipher.DoFinal(data);

}

///

/// RSA加密——Base64

///

/// 未加密字符串

/// 非对称密钥参数

/// 密文算法

/// 已加密Base64字符串

public static string EncryptToBase64(string data, AsymmetricKeyParameter parameters, string algorithm)

{

return Base64.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(data), parameters, algorithm));

}

///

/// RSA解密——Base64

///

/// 已加密Base64字符串

/// 非对称密钥参数

/// 密文算法

/// 未加密字符串

public static string DecryptFromBase64(string data, AsymmetricKeyParameter parameters, string algorithm)

{

return Encoding.UTF8.GetString(Decrypt(Base64.Decode(data), parameters, algorithm));

}

///

/// RSA加密——十六进制

///

/// 未加密字符串

/// 非对称密钥参数

/// 密文算法

/// 已加密十六进制字符串

public static string EncryptToHex(string data, AsymmetricKeyParameter parameters, string algorithm)

{

return Hex.ToHexString(Encrypt(Encoding.UTF8.GetBytes(data), parameters, algorithm));

}

///

/// RSA解密——十六进制

///

/// 已加密十六进制字符串

/// 非对称密钥参数

/// 密文算法

/// 未加密字符串

public static string DecryptFromHex(string data, AsymmetricKeyParameter parameters, string algorithm)

{

return Encoding.UTF8.GetString(Decrypt(Hex.Decode(data), parameters, algorithm));

}

RSA密文算法

public const string RSA_NONE_NoPadding = "RSA/NONE/NoPadding";

public const string RSA_NONE_PKCS1Padding = "RSA/NONE/PKCS1Padding";

public const string RSA_NONE_OAEPPadding = "RSA/NONE/OAEPPadding";

public const string RSA_NONE_OAEPWithSHA1AndMGF1Padding = "RSA/NONE/OAEPWithSHA1AndMGF1Padding";

public const string RSA_NONE_OAEPWithSHA224AndMGF1Padding = "RSA/NONE/OAEPWithSHA224AndMGF1Padding";

public const string RSA_NONE_OAEPWithSHA256AndMGF1Padding = "RSA/NONE/OAEPWithSHA256AndMGF1Padding";

public const string RSA_NONE_OAEPWithSHA384AndMGF1Padding = "RSA/NONE/OAEPWithSHA384AndMGF1Padding";

public const string RSA_NONE_OAEPWithMD5AndMGF1Padding = "RSA/NONE/OAEPWithMD5AndMGF1Padding";

public const string RSA_ECB_NoPadding = "RSA/ECB/NoPadding";

public const string RSA_ECB_PKCS1Padding = "RSA/ECB/PKCS1Padding";

public const string RSA_ECB_OAEPPadding = "RSA/ECB/OAEPPadding";

public const string RSA_ECB_OAEPWithSHA1AndMGF1Padding = "RSA/ECB/OAEPWithSHA1AndMGF1Padding";

public const string RSA_ECB_OAEPWithSHA224AndMGF1Padding = "RSA/ECB/OAEPWithSHA224AndMGF1Padding";

public const string RSA_ECB_OAEPWithSHA256AndMGF1Padding = "RSA/ECB/OAEPWithSHA256AndMGF1Padding";

public const string RSA_ECB_OAEPWithSHA384AndMGF1Padding = "RSA/ECB/OAEPWithSHA384AndMGF1Padding";

public const string RSA_ECB_OAEPWithMD5AndMGF1Padding = "RSA/ECB/OAEPWithMD5AndMGF1Padding";

......

编码算法

大家要明白,不管是对称算法还是非对称算法,其输入与输出均是字节数组,通常我们要结合编码算法对加密之后或解密之前的数据,进行编码操作。

BouncyCastle提供的Base64编码算法

namespace Org.BouncyCastle.Utilities.Encoders

{

public sealed class Base64

{

//

public static byte[] Decode(byte[] data);

//

public static byte[] Decode(string data);

//

public static int Decode(string data, Stream outStream);

//

public static byte[] Encode(byte[] data);

//

public static byte[] Encode(byte[] data, int off, int length);

//

public static int Encode(byte[] data, Stream outStream);

//

public static int Encode(byte[] data, int off, int length, Stream outStream);

public static string ToBase64String(byte[] data);

public static string ToBase64String(byte[] data, int off, int length);

}

}

BouncyCastle提供的Hex十六进制编码算法

namespace Org.BouncyCastle.Utilities.Encoders

{

//

// 摘要:

// Class to decode and encode Hex.

public sealed class Hex

{

//

public static byte[] Decode(byte[] data);

//

public static byte[] Decode(string data);

//

public static int Decode(string data, Stream outStream);

//

public static byte[] Encode(byte[] data);

//

public static byte[] Encode(byte[] data, int off, int length);

//

public static int Encode(byte[] data, Stream outStream);

//

public static int Encode(byte[] data, int off, int length, Stream outStream);

public static string ToHexString(byte[] data);

public static string ToHexString(byte[] data, int off, int length);

}

}

RSA加解密示例

private static void RSA_ECB_PKCS1Padding()

{

var data = "hello rsa";

Console.WriteLine($"加密原文:{data}");

// rsa pkcs8 private key encrypt

//algorithm rsa/ecb/pkcs1padding

var pkcs8data = RSA.EncryptToBase64(data, RSAUtilities.GetAsymmetricKeyParameterFormAsn1PrivateKey(pkcs8_1024_private_key),CipherAlgorithms.RSA_ECB_PKCS1Padding);

Console.WriteLine("密钥格式:pkcs8,密文算法:rsa/ecb/pkcs1padding,加密结果");

Console.WriteLine(pkcs8data);

//rsa pkcs1 private key encrypt

//algorithm rsa/ecb/pkcs1padding

var pkcs1data = RSA.EncryptToBase64(data, RSAUtilities.GetAsymmetricKeyParameterFormPrivateKey(pkcs1_1024_private_key),CipherAlgorithms.RSA_ECB_PKCS1Padding);

Console.WriteLine($"密钥格式:pkcs1,密文算法:rsa/ecb/pkcs1padding");

Console.WriteLine(pkcs1data);

Console.WriteLine($"加密结果比对是否一致:{pkcs8data.Equals(pkcs1data)}");

var _1024_public_key = RSAKeyConverter.GetPublicKeyFromPrivateKeyPkcs1(pkcs1_1024_private_key);

Console.WriteLine($"从pkcs1私钥中提取公钥:");

Console.WriteLine(_1024_public_key);

Console.WriteLine("使用公钥解密数据:");

//rsa public key decrypt

//algorithm rsa/ecb/pkcs1padding

Console.WriteLine(RSA.DecryptFromBase64(pkcs1data, RSAUtilities.GetAsymmetricKeyParameterFormPublicKey(_1024_public_key),CipherAlgorithms.RSA_ECB_PKCS1Padding));

Console.WriteLine();

}

下期预告

下一篇将介绍哈希算法(HMACSHA1、HMACSHA256、SHA1、SHA1WithRSA、SHA256、SHA256WithRSA),敬请期待…

2125309fb12077647ae74ffbd2090e44.png

97bc351681caf946541e25607a490b0d.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值