前言
C#有自己的一套生成密鑰、加解密的庫,但是跟其他文互通比較費勁,經過一翻比較後,筆者選擇了BouncyCastle這套庫,而這套庫的缺點是文檔很少,只能參考Java的代碼才把需求的功能實現。筆者下面提供的代碼是經過多語言環境驗證,可以與其他語言互通。
- C#、Golang、Python、Java(Android)之間Des、Rsa加解密互通系列之前言
- C#、Golang、Python、Java(Android)之間Des、Rsa加解密互通系列之C#
- C#、Golang、Python、Java(Android)之間Des、Rsa加解密互通系列之Golang
- C#、Golang、Python、Java(Android)之間Des、Rsa加解密互通系列之Python
- C#、Golang、Python、Java(Android)之間Des、Rsa加解密互通系列之Java(Android)
代碼
Des對稱加密工具類
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace lhtzbj12.Encryption
{
/// <summary>
/// Des對稱加密工具類
/// </summary>
public class DesHelper
{
/// <summary>
/// 加密
/// </summary>
/// <param name="data">待加密的數據</param>
/// <param name="key">加/解密key 8位</param>
/// <param name="iv">偏移向量 8位</param>
/// <param name="model">密碼模式</param>
/// <param name="padding">填充方式</param>
/// <returns></returns>
public static string Encrypt(string data, string key, string iv, CipherMode model = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
{
byte[] _KeyByte = null;
if (!string.IsNullOrWhiteSpace(key))
{
_KeyByte = Encoding.UTF8.GetBytes(key);
}
byte[] _IVByte = null;
if (!string.IsNullOrWhiteSpace(iv))
{
_IVByte = Encoding.UTF8.GetBytes(iv);
}
var sa = new DESCryptoServiceProvider();
sa.Mode = model;
sa.Padding = padding;
var ct = sa.CreateEncryptor(_KeyByte, _IVByte);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
byte[] byt = Encoding.UTF8.GetBytes(data);
cs.Write(byt, 0, byt.Length);
cs.FlushFinalBlock();
cs.Close();
return Convert.ToBase64String(ms.ToArray());
}
/// <summary>
/// 解密
/// </summary>
/// <param name="encData">加密生成的Base64密文</param>
/// <param name="key">加/解密key 8位</param>
/// <param name="iv">偏移向量 8位</param>
/// <param name="model">密碼模式</param>
/// <param name="padding">填充方式</param>
/// <returns></returns>
public static string Decrypt(string encData, string key, string iv, CipherMode model = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
{
byte[] _KeyByte = null;
if (!string.IsNullOrWhiteSpace(key))
{
_KeyByte = Encoding.UTF8.GetBytes(key);
}
byte[] _IVByte = null;
if (!string.IsNullOrWhiteSpace(iv))
{
_IVByte = Encoding.UTF8.GetBytes(iv);
}
using (ICryptoTransform ct = new DESCryptoServiceProvider()
{ Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 }.CreateDecryptor(_KeyByte, _IVByte))
{
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
{
byte[] byt = Convert.FromBase64String(encData);
try
{
cs.Write(byt, 0, byt.Length);
cs.FlushFinalBlock();
cs.Close();
}
catch (Exception)
{
return string.Empty;
}
}
return Encoding.UTF8.GetString(ms.ToArray());
}
}
}
}
}
Rsa密鑰對生成、加載(讀取)工具類
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using System.IO;
using System.Text.RegularExpressions;
namespace lhtzbj12.Encryption
{
/// <summary>
/// Rsa密鑰對生成工具
/// </summary>
public class RsaKeyHelper
{
public static void GenKey(out string publicKey, out string privateKey, out string privateKeyPk8)
{
publicKey = string.Empty;
privateKey = string.Empty;
privateKeyPk8 = string.Empty;
try
{
//RSA密鑰對的構造器
RsaKeyPairGenerator r = new RsaKeyPairGenerator();
//RSA密鑰構造器的參數
RsaKeyGenerationParameters param = new RsaKeyGenerationParameters(
Org.BouncyCastle.Math.BigInteger.ValueOf(3),
new SecureRandom(),
1024, //密鑰長度
25);
r.Init(param);
AsymmetricCipherKeyPair keyPair = r.GenerateKeyPair();
//獲取公鑰和密鑰
AsymmetricKeyParameter private_key = keyPair.Private;
AsymmetricKeyParameter public_key = keyPair.Public;
if (((RsaKeyParameters)public_key).Modulus.BitLength < 1024)
{
Console.WriteLine("failed key generation (1024) length test");
}
using (TextWriter textWriter = new StringWriter())
{
PemWriter pemWriter = new PemWriter(textWriter);
pemWriter.WriteObject(keyPair.Private);
pemWriter.Writer.Flush();
privateKey = textWriter.ToString();
}
using (TextWriter textpubWriter = new StringWriter())
{
PemWriter pempubWriter = new PemWriter(textpubWriter);
pempubWriter.WriteObject(keyPair.Public);
pempubWriter.Writer.Flush();
publicKey = textpubWriter.ToString();
}
//keyPair = ReadPem(privateKey); // 直接讀取字符串生成密碼鑰
//public_key = keyPair.Public;//公鑰
//private_key = keyPair.Private;//私鑰
// 前面私鑰爲pkcs1格式,經過下面處理後,變成pkcs8格式
SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(public_key);
PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(private_key);
Asn1Object asn1ObjectPublic = subjectPublicKeyInfo.ToAsn1Object();
byte[] publicInfoByte = asn1ObjectPublic.GetEncoded();
Asn1Object asn1ObjectPrivate = privateKeyInfo.ToAsn1Object();
byte[] privateInfoByte = asn1ObjectPrivate.GetEncoded();
var pubkeyb64 = Convert.ToBase64String(publicInfoByte);
// 這裏生成的是Pkcs8的密鑰
privateKeyPk8 = PrivateKeyPk8Format(Convert.ToBase64String(privateInfoByte));
privateKey = PrivateKeyFormat(privateKey);
publicKey = PublicKeyFormat(publicKey);
}
catch (Exception ex) {
throw ex;
}
}
/// <summary>
/// 加載Pkcs8格式的私鑰
/// </summary>
/// <param name="privateKey"></param>
/// <returns></returns>
public static AsymmetricKeyParameter loadPrivateKeyPk8(string privateKey)
{
try
{
privateKey = KeyClear(privateKey);
byte[] prikey = Convert.FromBase64String(privateKey);
Asn1Object priKeyObj = Asn1Object.FromByteArray(prikey);//這裏也可以從流中讀取,從本地導入
AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(PrivateKeyInfo.GetInstance(priKeyObj));
return priKey;
}
catch (Exception)
{
throw new Exception("密鑰格式不正確");
}
}
/// <summary>
/// 加載Pkcs1格式的私鑰
/// </summary>
/// <param name="privateKey"></param>
/// <returns></returns>
public static AsymmetricKeyParameter loadPrivateKeyPk1(string privateKey)
{
AsymmetricCipherKeyPair keyPair = null;
try
{
keyPair = ReadPem(privateKey); // 直接讀取字符串生成密碼鑰
}
catch (Exception)
{
throw new Exception("密鑰格式不正確");
}
try
{
AsymmetricKeyParameter private_key = keyPair.Private;
// 前面私鑰爲pkcs1格式,經過下面處理後,變成pkcs8格式
PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(private_key);
Asn1Object asn1ObjectPrivate = privateKeyInfo.ToAsn1Object();
AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(PrivateKeyInfo.GetInstance(asn1ObjectPrivate));
return priKey;
}
catch (Exception)
{
throw new Exception("加載失敗");
}
}
/// <summary>
/// 加載公鑰
/// </summary>
/// <param name="publicKey"></param>
/// <returns></returns>
public static AsymmetricKeyParameter loadPublicKey(string publicKey)
{
try
{
publicKey = KeyClear(publicKey);
byte[] pubkey = Convert.FromBase64String(publicKey);
Asn1Object pubKeyObj = Asn1Object.FromByteArray(pubkey);//這裏也可以從流中讀取,從本地導入
AsymmetricKeyParameter pubKey = PublicKeyFactory.CreateKey(SubjectPublicKeyInfo.GetInstance(pubKeyObj));
return pubKey;
}
catch (Exception)
{
throw new Exception("密鑰格式不正確");
}
}
/// <summary>
/// 將Pkcs1格式的私轉成Pkcs8格式
/// </summary>
/// <param name="privateKey"></param>
/// <returns></returns>
public static string ConvertPriPk1ToPk8(string privateKey)
{
AsymmetricCipherKeyPair keyPair = null;
try
{
keyPair = ReadPem(privateKey); // 直接讀取字符串生成密碼鑰
}
catch (Exception)
{
throw new Exception("密鑰格式不正確");
}
try
{
AsymmetricKeyParameter private_key = keyPair.Private;
AsymmetricKeyParameter public_key = keyPair.Public;
// 前面私鑰爲pkcs1格式,經過下面處理後,變成pkcs8格式
SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(public_key);
PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(private_key);
Asn1Object asn1ObjectPublic = subjectPublicKeyInfo.ToAsn1Object();
byte[] publicInfoByte = asn1ObjectPublic.GetEncoded();
Asn1Object asn1ObjectPrivate = privateKeyInfo.ToAsn1Object();
byte[] privateInfoByte = asn1ObjectPrivate.GetEncoded();
var pubkeyb64 = Convert.ToBase64String(publicInfoByte);
// 這裏生成的是Pkcs8的密鑰
return PrivateKeyFormat(Convert.ToBase64String(privateInfoByte));
}
catch (Exception)
{
throw new Exception("轉換失敗");
}
}
public static string KeyClear(string key)
{
key = Regex.Replace(key, @"(-----BEGIN PRIVATE KEY-----)|(-----END PRIVATE KEY-----)|(-----BEGIN RSA PRIVATE KEY-----)|(-----END RSA PRIVATE KEY-----)|(-----BEGIN PUBLIC KEY-----)|(-----END PUBLIC KEY-----)|(-----BEGIN RSA PUBLIC KEY-----)|(-----END RSA PUBLIC KEY-----)|\n|\r", "");
return key;
}
private static string PrivateKeyFormat(string privateKey)
{
privateKey = KeyClear(privateKey);
privateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" + privateKey + "\r\n-----END RSA PRIVATE KEY-----";
return privateKey;
}
private static string PrivateKeyPk8Format(string privateKey)
{
privateKey = KeyClear(privateKey);
privateKey = "-----BEGIN PRIVATE KEY-----\r\n" + privateKey + "\r\n-----END PRIVATE KEY-----";
return privateKey;
}
private static string PublicKeyFormat(string publicKey)
{
publicKey = KeyClear(publicKey);
publicKey = "-----BEGIN PUBLIC KEY-----\r\n" + publicKey + "\r\n-----END PUBLIC KEY-----";
return publicKey;
}
static AsymmetricCipherKeyPair ReadPem(string pem)
{
using (TextReader reader = new StringReader(pem))
{
var obj = new Org.BouncyCastle.OpenSsl.PemReader(reader).ReadObject();
return obj as AsymmetricCipherKeyPair;
}
}
}
}
Rsa加密、解密、簽名、驗籤工具類
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace lhtzbj12.Encryption
{
/// <summary>
/// Rsa非對稱加密工具類
/// </summary>
public class RsaBCHelper
{
/// <summary>
/// 簽名
/// </summary>
/// <param name="content">待簽名字符串</param>
/// <param name="privateKey">私鑰</param>
/// <returns>簽名後字符串</returns>
public static string Sign(string content, string privateKey)
{
AsymmetricKeyParameter priKey = RsaKeyHelper.loadPrivateKeyPk1(privateKey);
ISigner sig = SignerUtilities.GetSigner("SHA256withRSA"); //其他算法 如SHA1withRSA
sig.Init(true, priKey);
var bytes = Encoding.UTF8.GetBytes(content);
sig.BlockUpdate(bytes, 0, bytes.Length);
byte[] signature = sig.GenerateSignature();
var signedString = Convert.ToBase64String(signature);
return signedString;
}
/// <summary>
/// 驗籤
/// </summary>
/// <param name="content">待驗簽字符串</param>
/// <param name="signedString">簽名</param>
/// <param name="publicKey">公鑰</param>
/// <returns>true(通過),false(不通過)</returns>
public static bool Verify(string content, string signedString, string publicKey)
{
AsymmetricKeyParameter pubKey = RsaKeyHelper.loadPublicKey(publicKey);
ISigner signer = SignerUtilities.GetSigner("SHA256withRSA"); //其他算法 如SHA1withRSA
signer.Init(false, pubKey);
var expectedSig = Convert.FromBase64String(signedString);
var msgBytes = Encoding.UTF8.GetBytes(content);
signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
return signer.VerifySignature(expectedSig);
}
/// <summary>
/// 公鑰加密
/// </summary>
/// <param name="resData">需要加密的字符串</param>
/// <param name="publicKey">公鑰</param>
/// <returns>明文</returns>
public static string Encrypt(string resData, string publicKey)
{
try
{
AsymmetricKeyParameter pubKey = RsaKeyHelper.loadPublicKey(publicKey);
IBufferedCipher cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
cipher.Init(true, pubKey);//true表示加密
var data = Encoding.UTF8.GetBytes(resData.Trim());
byte[] encryptData = cipher.DoFinal(data);
return Convert.ToBase64String(encryptData);
}
catch (Exception)
{
throw new Exception("加密失敗");
}
}
/// <summary>
/// 私鑰解密
/// </summary>
/// <param name="resData">加密字符串</param>
/// <param name="privateKey">私鑰</param>
/// <param name="input_charset">編碼格式</param>
/// <returns>明文</returns>
public static string Decrypt(string resData, string privateKey)
{
try
{
AsymmetricKeyParameter priKey = RsaKeyHelper.loadPrivateKeyPk1(privateKey);
IBufferedCipher cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
cipher.Init(false, priKey);//false表示解密
var encryptData = Convert.FromBase64String(resData);
var decryptData = cipher.DoFinal(encryptData);
return Encoding.UTF8.GetString(decryptData);
}
catch (Exception) {
throw new Exception("解密失敗");
}
}
/// <summary>
/// 私鑰加密
/// </summary>
/// <param name="resData">需要加密的字符串</param>
/// <param name="privateKey">私鑰</param>
/// <returns>明文</returns>
public static string EncryptByPrivateKey(string resData, string privateKey)
{
try
{
AsymmetricKeyParameter priKey = RsaKeyHelper.loadPrivateKeyPk1(privateKey);
IBufferedCipher cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
cipher.Init(true, priKey);//true表示加密
var data = Encoding.UTF8.GetBytes(resData.Trim());
byte[] encryptData = cipher.DoFinal(data);
return Convert.ToBase64String(encryptData);
}
catch (Exception)
{
throw new Exception("加密失敗");
}
}
/// <summary>
/// 公鑰解密
/// </summary>
/// <param name="resData">加密字符串</param>
/// <param name="publicKey">公鑰</param>
/// <returns>明文</returns>
public static string DecryptByPublicKey(string resData, string publicKey)
{
try
{
AsymmetricKeyParameter pubKey = RsaKeyHelper.loadPublicKey(publicKey);
IBufferedCipher cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
cipher.Init(false, pubKey);//false表示解密
var encryptData = Convert.FromBase64String(resData);
var decryptData = cipher.DoFinal(encryptData);
return Encoding.UTF8.GetString(decryptData);
}
catch (Exception)
{
throw new Exception("解密失敗");
}
}
}
}