算法 | 密钥类型 | 加密解密的特点 |
---|---|---|
对称加密算法 | 通讯双方有且只有一个共同的密钥K | 加密方使用密钥K加密,解密方使用密钥K解密 |
非对称加密算法 | 密钥有分私钥和公钥; | 通讯双方分别持有自己的私钥和对方的公钥;密方使用自己的私钥加密数据,解密方使用对方的公钥解密数据;加密方使用对方的公钥加密数据,解密方使用自己的私钥解密数据; |
不可逆加密算法 | 无 | 加密后不可解密成原有明文 |
已破解,不再安全,基本没有企业在用了
计算密钥时间太长、加密效率不高,所以也基本上不用
常用的电子邮件加密算法
工作模式只有ECB
密钥长度128位
算法公开、计算量小、加密速度快、加密效率高、被破解风险高。
最常用的对称加密算法
密钥建立时间短、灵敏性好、内存需求低(不管怎样,反正就是好)
实际使用中,使用工作模式为CTR(最好用BC去实现),此工作模式需要引入IV参数(16位的字节数组)
密钥长度128/192/256,其中192与256需要配置无政策限制权限文件(JDK6)
填充模式最常用的两种PKCS5Padding和PKCS7Padding,其中后者只有BC独有。
#region AES加密解密
///
/// AES base64 加密算法;Key 为16位
///
/// 需要加密的字符串
///
public static string RST_AesEncrypt_Base64(string Data)
{
if (string.IsNullOrEmpty(Data))
{
return null;
}
if (string.IsNullOrEmpty(Key))
{
return null;
}
string Vector = Key.Substring(0, 16);
Byte[] plainBytes = Encoding.UTF8.GetBytes(Data);
Byte[] bKey = new Byte[32];
Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);
Byte[] bVector = new Byte[16];
Array.Copy(Encoding.UTF8.GetBytes(Vector.PadRight(bVector.Length)), bVector, bVector.Length);
Byte[] Cryptograph = null; // 加密后的密文
Rijndael Aes = Rijndael.Create();
//add
Aes.Mode = CipherMode.CBC;//兼任其他语言的des
Aes.BlockSize = 128;
Aes.Padding = PaddingMode.PKCS7;
//add end
try
{
// 开辟一块内存流
using (MemoryStream Memory = new MemoryStream())
{
// 把内存流对象包装成加密流对象
using (CryptoStream Encryptor = new CryptoStream(Memory,
Aes.CreateEncryptor(bKey, bVector),
CryptoStreamMode.Write))
{
// 明文数据写入加密流
Encryptor.Write(plainBytes, 0, plainBytes.Length);
Encryptor.FlushFinalBlock();
Cryptograph = Memory.ToArray();
}
}
}
catch
{
Cryptograph = null;
}
return Convert.ToBase64String(Cryptograph);
}
///
/// AES base64 解密算法;Key为16位
///
/// 需要解密的字符串
/// Key为16位 密钥
///
public static string RST_AesDecrypt_Base64(string Data)
{
try
{
if (string.IsNullOrEmpty(Data))
{
return null;
}
if (string.IsNullOrEmpty(Key))
{
return null;
}
string Vector = Key.Substring(0, 16);
Byte[] encryptedBytes = Convert.FromBase64String(Data);
Byte[] bKey = new Byte[32];
Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);
Byte[] bVector = new Byte[16];
Array.Copy(Encoding.UTF8.GetBytes(Vector.PadRight(bVector.Length)), bVector, bVector.Length);
Byte[] original = null; // 解密后的明文
Rijndael Aes = Rijndael.Create();
//add
Aes.Mode = CipherMode.CBC;//兼任其他语言的des
Aes.BlockSize = 128;
Aes.Padding = PaddingMode.PKCS7;
//add end
try
{
// 开辟一块内存流,存储密文
using (MemoryStream Memory = new MemoryStream(encryptedBytes))
{
//把内存流对象包装成加密流对象
using (CryptoStream Decryptor = new CryptoStream(Memory,
Aes.CreateDecryptor(bKey, bVector),
CryptoStreamMode.Read))
{
// 明文存储区
using (MemoryStream originalMemory = new MemoryStream())
{
Byte[] Buffer = new Byte[1024];
Int32 readBytes = 0;
while ((readBytes = Decryptor.Read(Buffer, 0, Buffer.Length)) > 0)
{
originalMemory.Write(Buffer, 0, readBytes);
}
original = originalMemory.ToArray();
}
}
}
}
catch
{
original = null;
}
return Encoding.UTF8.GetString(original);
}
catch { return null; }
}
///
/// 密钥16位或者32位的AES base64加密
///
/// 需要进行加密的明文字符串
/// 16位或者32位的密钥
/// 16位以上的向量;默认为:"*Gc_Yy_Cq_@_Ztl_99*"
/// AES加密之后的密文
public static string AesEncrypt(string value, string key, string iv = "")
{
if (string.IsNullOrEmpty(value)) return string.Empty;
if (string.IsNullOrEmpty(key))
{
key = Key;
}
if (key.Length < 16) throw new Exception("指定的密钥长度不能少于16位。");
if (key.Length > 32) throw new Exception("指定的密钥长度不能多于32位。");
if (key.Length != 16 && key.Length != 24 && key.Length != 32) throw new Exception("指定的密钥长度不明确。");
if (string.IsNullOrEmpty(iv))
{
iv = vector;
}
if (!string.IsNullOrEmpty(iv))
{
if (iv.Length < 16) throw new Exception("指定的向量长度不能少于16位。");
}
var _keyByte = Encoding.UTF8.GetBytes(key);
var _valueByte = Encoding.UTF8.GetBytes(value);
using (var aes = new RijndaelManaged())
{
aes.IV = !string.IsNullOrEmpty(iv) ? Encoding.UTF8.GetBytes(iv) : Encoding.UTF8.GetBytes(key.Substring(0, 16));
aes.Key = _keyByte;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
var cryptoTransform = aes.CreateEncryptor();
var resultArray = cryptoTransform.TransformFinalBlock(_valueByte, 0, _valueByte.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
}
///
/// 密钥16位或者32位的AES base64解密
///
/// 需要解密的密文
/// 16位或者32位的密钥需和加密时的密钥保持一致
/// 16位以上的向量需和加密时的向量保持一致;默认为:"*Gc_Yy_Cq_@_Ztl_99*"
/// AES解密之后的明文
public static string AesDecrypt(string value, string key, string iv = "")
{
if (string.IsNullOrEmpty(value)) return string.Empty;
if (string.IsNullOrEmpty(key))
{
key = Key;
}
if (key.Length < 16) throw new Exception("指定的密钥长度不能少于16位。");
if (key.Length > 32) throw new Exception("指定的密钥长度不能多于32位。");
if (key.Length != 16 && key.Length != 24 && key.Length != 32) throw new Exception("指定的密钥长度不明确。");
if (string.IsNullOrEmpty(iv))
{
iv = vector;
}
if (!string.IsNullOrEmpty(iv))
{
if (iv.Length < 16) throw new Exception("指定的向量长度不能少于16位。");
}
var _keyByte = Encoding.UTF8.GetBytes(key);
var _valueByte = Convert.FromBase64String(value);
using (var aes = new RijndaelManaged())
{
aes.IV = !string.IsNullOrEmpty(iv) ? Encoding.UTF8.GetBytes(iv) : Encoding.UTF8.GetBytes(key.Substring(0, 16));
aes.Key = _keyByte;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
var cryptoTransform = aes.CreateDecryptor();
var resultArray = cryptoTransform.TransformFinalBlock(_valueByte, 0, _valueByte.Length);
return Encoding.UTF8.GetString(resultArray);
}
}
#endregion
RSA公钥加密算法是1977年由罗纳德·李维斯特
(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。RSA就是他们三人姓氏开头字母拼在一起组成的
RSA是目前最有影响力和最常用的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。
加密和解密花费时间长、速度慢,它不适合于对文件加密而只适用于对少量数据进行加密。
#region RSA加密解密:采用公钥,私钥的模式
#region 私钥加密,公钥解密
///
/// RSA私钥加密
///
/// Java格式的RSA私钥 base64格式
/// 待加密的数据;调用方法Encoding.GetEncoding("UTF-8").GetBytes(contentData)
/// 加密算法
/// RSA私钥加密之后的密文
public static string EncryptWithPrivateKey(string privateKey, byte[] contentData, string algorithm = "RSA/ECB/PKCS1Padding")
{
return Convert.ToBase64String(EncryptWithPrivateKey(Convert.FromBase64String(privateKey), contentData, algorithm));
}
private static byte[] Transform(AsymmetricKeyParameter key, byte[] contentData, string algorithm, bool forEncryption)
{
var c = CipherUtilities.GetCipher(algorithm);
c.Init(forEncryption, new ParametersWithRandom(key));
return c.DoFinal(contentData);
}
///
/// RSA私钥加密
///
/// Java格式的RSA私钥
/// 待加密的数据;调用方法Encoding.GetEncoding("UTF-8").GetBytes(contentData)
/// 加密算法
/// RSA私钥加密之后的密文
public static byte[] EncryptWithPrivateKey(byte[] privateKey, byte[] contentData, string algorithm = "RSA/ECB/PKCS1Padding")
{
RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(privateKey);
return Transform(privateKeyParam, contentData, algorithm, true);
}
///
/// RSA公钥解密
///
/// Java格式的RSA公钥 base64格式
/// 待解密数据 base64格式
/// 解密出来的数据编码格式,默认UTF-8
/// 加密算法
/// RSA私钥解密之后的明文
public static string DecryptWithPublicKey(string publicKey, string content, string encoding = "UTF-8", string algorithm = "RSA/ECB/PKCS1Padding")
{
return Encoding.GetEncoding(encoding).GetString(DecryptWithPublicKey(Convert.FromBase64String(publicKey), Convert.FromBase64String(content), algorithm));
}
///
/// RSA公钥解密
///
/// Java格式的RSA公钥
/// 待解密数据
/// 加密算法
/// RSA私钥解密之后的明文
public static byte[] DecryptWithPublicKey(byte[] publicKey, byte[] contentData, string algorithm = "RSA/ECB/PKCS1Padding")
{
RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(publicKey);
return Transform(publicKeyParam, contentData, algorithm, false);
}
#endregion
#region 公钥加密,私钥解密
///
/// RSA公钥加密
///
/// 加密公钥;为空则默认系统公钥
/// 需要加密的明文字符串
/// 编码格式;默认:UTF-8
/// RSA公钥加密的密文
public static string RSAEncrypt_Public(string xmlPublicKey, string enptStr, string encoding = "UTF-8")
{
if (string.IsNullOrEmpty(xmlPublicKey))
{
xmlPublicKey = _publicKey;
}
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
byte[] cipherbytes;
rsa.FromXmlString(xmlPublicKey);
cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(enptStr), false);
return Convert.ToBase64String(cipherbytes);
}
}
///
/// RSA私钥解密
///
/// 解密私钥;为空则默认系统公钥
/// 需要加密的明文字符串
/// 编码格式;默认:UTF-8
/// RSA私钥解密的明文
public static string RSADecrypt_Private(string xmlPrivateKey, string enptStr, string encoding = "UTF-8")
{
if (string.IsNullOrEmpty(xmlPrivateKey))
{
xmlPrivateKey = _privateKey;
}
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
byte[] cipherbytes;
rsa.FromXmlString(xmlPrivateKey);
cipherbytes = rsa.Decrypt(Convert.FromBase64String(enptStr), false);
return Encoding.GetEncoding(encoding).GetString(cipherbytes);
}
}
#endregion
#region 使用同一容器的名称进行RSA加密解密
///
/// 进行 RSA 加密
///
/// 源字符串
/// 加密后字符串
public static string RsaEncrypt(string sourceStr)
{
Param = new CspParameters();
//密匙容器的名称,保持加密解密一致才能解密成功
Param.KeyContainerName = "Navis";
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(Param))
{
//将要加密的字符串转换成字节数组
byte[] plaindata = Encoding.Default.GetBytes(sourceStr);
//通过字节数组进行加密
byte[] encryptdata = rsa.Encrypt(plaindata, false);
//将加密后的字节数组转换成字符串
return Convert.ToBase64String(encryptdata);
}
}
///
/// 通过RSA 加密方式进行解密
///
/// 加密字符串
/// 解密后字符串
public static string RsaDesEncrypt(string codingStr)
{
Param = new CspParameters();
Param.KeyContainerName = "Navis";
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(Param))
{
byte[] encryptdata = Convert.FromBase64String(codingStr);
byte[] decryptdata = rsa.Decrypt(encryptdata, false);
return Encoding.Default.GetString(decryptdata);
}
}
#endregion
#region RSA分段加密:待加密的字符串拆开,每段长度都小于等于限制长度,然后分段加密
///
/// RSA分段加密
///
/// RSA C#公钥
/// 需要进行RSA加密的长字符串
/// 返回RSA加密后的密文
public static String SubRSAEncrypt(string xmlPublicKey, string enptStr)
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(xmlPublicKey);
Byte[] bytes = Encoding.Default.GetBytes(enptStr);
int MaxBlockSize = provider.KeySize / 8 - 11; //加密块最大长度限制
if (bytes.Length <= MaxBlockSize)
return Convert.ToBase64String(provider.Encrypt(bytes, false));
using (MemoryStream PlaiStream = new MemoryStream(bytes))
using (MemoryStream CrypStream = new MemoryStream())
{
Byte[] Buffer = new Byte[MaxBlockSize];
int BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
while (BlockSize > 0)
{
Byte[] ToEncrypt = new Byte[BlockSize];
Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);
Byte[] Cryptograph = provider.Encrypt(ToEncrypt, false);
CrypStream.Write(Cryptograph, 0, Cryptograph.Length);
BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
}
return Convert.ToBase64String(CrypStream.ToArray(), Base64FormattingOptions.None);
}
}
///
/// RSA分段解密,应对长字符串
///
/// RSA C#私钥
/// 需要解密的长字符串
/// 返回RSA分段解密的明文
public static String SubRSADecrypt(string xmlPrivateKey, string enptStr)
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(xmlPrivateKey);
Byte[] bytes = Convert.FromBase64String(enptStr);
int MaxBlockSize = provider.KeySize / 8; //解密块最大长度限制
if (bytes.Length <= MaxBlockSize)
return Encoding.Default.GetString(provider.Decrypt(bytes, false));
using (MemoryStream CrypStream = new MemoryStream(bytes))
using (MemoryStream PlaiStream = new MemoryStream())
{
Byte[] Buffer = new Byte[MaxBlockSize];
int BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);
while (BlockSize > 0)
{
Byte[] ToDecrypt = new Byte[BlockSize];
Array.Copy(Buffer, 0, ToDecrypt, 0, BlockSize);
Byte[] Plaintext = provider.Decrypt(ToDecrypt, false);
PlaiStream.Write(Plaintext, 0, Plaintext.Length);
BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);
}
return Encoding.Default.GetString(PlaiStream.ToArray());
}
}
#endregion
#endregion
数字签名算法,是一种标准的 DSS(数字签名标准);
ECC和RSA相比,在许多方面都有对绝对的优势,主要体现在以下方面:
SM2算法就是ECC椭圆曲线密码机制,但在签名、密钥交换方面不同于ECDSA、ECDH等国际标准,而是采取了更为安全的机制。另外,SM2推荐了一条256位的曲线作为标准曲线。属于国密,即国产密码算法(国密算法)是指国家密码局认定的国产商用密码算法
SM2主类
using System;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System.Text;
namespace Com.Mlq.SM
{
public class SM2
{
public static SM2 Instance
{
get
{
return new SM2();
}
}
public static SM2 InstanceTest
{
get
{
return new SM2();
}
}
public static readonly string[] sm2_param = {
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",// p,0
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",// a,1
"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",// b,2
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",// n,3
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",// gx,4
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0" // gy,5
};
public string[] ecc_param = sm2_param;
public readonly BigInteger ecc_p;
public readonly BigInteger ecc_a;
public readonly BigInteger ecc_b;
public readonly BigInteger ecc_n;
public readonly BigInteger ecc_gx;
public readonly BigInteger ecc_gy;
public readonly ECCurve ecc_curve;
public readonly ECPoint ecc_point_g;
public readonly ECDomainParameters ecc_bc_spec;
public readonly ECKeyPairGenerator ecc_key_pair_generator;
private SM2()
{
ecc_param = sm2_param;
ECFieldElement ecc_gx_fieldelement;
ECFieldElement ecc_gy_fieldelement;
ecc_p = new BigInteger(ecc_param[0], 16);
ecc_a = new BigInteger(ecc_param[1], 16);
ecc_b = new BigInteger(ecc_param[2], 16);
ecc_n = new BigInteger(ecc_param[3], 16);
ecc_gx = new BigInteger(ecc_param[4], 16);
ecc_gy = new BigInteger(ecc_param[5], 16);
ecc_gx_fieldelement = new FpFieldElement(ecc_p, ecc_gx);
ecc_gy_fieldelement = new FpFieldElement(ecc_p, ecc_gy);
ecc_curve = new FpCurve(ecc_p, ecc_a, ecc_b);
ecc_point_g = new FpPoint(ecc_curve, ecc_gx_fieldelement, ecc_gy_fieldelement);
ecc_bc_spec = new ECDomainParameters(ecc_curve, ecc_point_g, ecc_n);
ECKeyGenerationParameters ecc_ecgenparam;
ecc_ecgenparam = new ECKeyGenerationParameters(ecc_bc_spec, new SecureRandom());
ecc_key_pair_generator = new ECKeyPairGenerator();
ecc_key_pair_generator.Init(ecc_ecgenparam);
}
public virtual byte[] Sm2GetZ(byte[] userId, ECPoint userKey)
{
SM3Digest sm3 = new SM3Digest();
byte[] p;
// userId length
int len = userId.Length * 8;
sm3.Update((byte) (len >> 8 & 0x00ff));
sm3.Update((byte) (len & 0x00ff));
// userId
sm3.BlockUpdate(userId, 0, userId.Length);
// a,b
p = ecc_a.ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
p = ecc_b.ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
// gx,gy
p = ecc_gx.ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
p = ecc_gy.ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
// x,y
p = userKey.X.ToBigInteger().ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
p = userKey.Y.ToBigInteger().ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
// Z
byte[] md = new byte[sm3.GetDigestSize()];
sm3.DoFinal(md, 0);
return md;
}
}
}
SM2工具类
using Com.Mlq.SM;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Com.Mlq.SM
{
class SM2Utils
{
public static void GenerateKeyPair()
{
SM2 sm2 = SM2.Instance;
AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.GenerateKeyPair();
ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.Private;
ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.Public;
BigInteger privateKey = ecpriv.D;
ECPoint publicKey = ecpub.Q;
System.Console.Out.WriteLine("公钥: " + Encoding.Default.GetString(Hex.Encode(publicKey.GetEncoded())).ToUpper());
System.Console.Out.WriteLine("私钥: " + Encoding.Default.GetString(Hex.Encode(privateKey.ToByteArray())).ToUpper());
}
public static String Encrypt(byte[] publicKey,byte[] data)
{
if (null == publicKey || publicKey.Length == 0)
{
return null;
}
if (data == null || data.Length == 0)
{
return null;
}
byte[] source = new byte[data.Length];
Array.Copy(data, 0, source, 0, data.Length);
Cipher cipher = new Cipher();
SM2 sm2 = SM2.Instance;
ECPoint userKey = sm2.ecc_curve.DecodePoint(publicKey);
ECPoint c1 = cipher.Init_enc(sm2, userKey);
cipher.Encrypt(source);
byte[] c3 = new byte[32];
cipher.Dofinal(c3);
String sc1 = Encoding.Default.GetString(Hex.Encode(c1.GetEncoded()));
String sc2 = Encoding.Default.GetString(Hex.Encode(source));
String sc3 = Encoding.Default.GetString(Hex.Encode(c3));
return (sc1 + sc2 + sc3).ToUpper();
}
public static byte[] Decrypt(byte[] privateKey, byte[] encryptedData)
{
if (null == privateKey || privateKey.Length == 0)
{
return null;
}
if (encryptedData == null || encryptedData.Length == 0)
{
return null;
}
String data = Encoding.Default.GetString(Hex.Encode(encryptedData));
byte[] c1Bytes = Hex.Decode(Encoding.Default.GetBytes(data.Substring(0 , 130)));
int c2Len = encryptedData.Length - 97;
byte[] c2 = Hex.Decode(Encoding.Default.GetBytes(data.Substring(130 , 2 * c2Len)));
byte[] c3 = Hex.Decode(Encoding.Default.GetBytes(data.Substring(130 + 2 * c2Len , 64)));
SM2 sm2 = SM2.Instance;
BigInteger userD = new BigInteger(1, privateKey);
ECPoint c1 = sm2.ecc_curve.DecodePoint(c1Bytes);
Cipher cipher = new Cipher();
cipher.Init_dec(userD, c1);
cipher.Decrypt(c2);
cipher.Dofinal(c3);
return c2;
}
//[STAThread]
//public static void Main()
//{
// GenerateKeyPair();
// String plainText = "ererfeiisgod";
// byte[] sourceData = Encoding.Default.GetBytes(plainText);
// //下面的秘钥可以使用generateKeyPair()生成的秘钥内容
// // 国密规范正式私钥
// String prik = "3690655E33D5EA3D9A4AE1A1ADD766FDEA045CDEAA43A9206FB8C430CEFE0D94";
// // 国密规范正式公钥
// String pubk = "04F6E0C3345AE42B51E06BF50B98834988D54EBC7460FE135A48171BC0629EAE205EEDE253A530608178A98F1E19BB737302813BA39ED3FA3C51639D7A20C7391A";
// System.Console.Out.WriteLine("加密: ");
// String cipherText = SM2Utils.Encrypt(Hex.Decode(pubk), sourceData);
// System.Console.Out.WriteLine(cipherText);
// System.Console.Out.WriteLine("解密: ");
// plainText = Encoding.Default.GetString(SM2Utils.Decrypt(Hex.Decode(prik), Hex.Decode(cipherText)));
// System.Console.Out.WriteLine(plainText);
// Console.ReadLine();
//}
}
}
散列是信息的提炼,通常其长度要比信息小得多,且为一个固定长度。加密性强的散列一定是不可逆的,这就意味着通过散列结果,无法推出任何部分的原始信息。任何输入信息的变化,哪怕仅一位,都将导致散列结果的明显变化,这称之为雪崩效应。散列还应该是防冲突的,即找不出具有相同散列结果的两条信息。具有这些特性的散列结果就可以用于验证信息是否被修改。
///
/// SHA1 加密
///
/// 需要加密字符串
/// 指定加密编码
/// 大小写格式(大写:X2;小写:x2)默认小写
public static string SHA1Encrypt(string content, Encoding encode, string upperOrLower = "x2")
{
try
{
var buffer = encode.GetBytes(content);//用指定编码转为bytes数组
var data = SHA1.Create().ComputeHash(buffer);
var sb = new StringBuilder();
foreach (var t in data)
{
sb.Append(t.ToString(upperOrLower));
}
return sb.ToString();
}
catch (Exception ex)
{
return "SHA1加密出错:" + ex.Message;
}
}
///
/// SHA256加密
///
/// 要加密的string字符串
/// SHA256加密之后的密文
public static string SHA256Encrypt(string strIN)
{
byte[] tmpByte;
SHA256 sha256 = new SHA256Managed();
tmpByte = sha256.ComputeHash(GetKeyByteArray(strIN));
StringBuilder rst = new StringBuilder();
for (int i = 0; i < tmpByte.Length; i++)
{
rst.Append(tmpByte[i].ToString("x2"));
}
sha256.Clear();
return rst.ToString();
}
///
/// 获取要加密的string字符串字节数组
///
/// 待加密字符串
/// 加密数组
private static byte[] GetKeyByteArray(string strKey)
{
UTF8Encoding Asc = new UTF8Encoding();
int tmpStrLen = strKey.Length;
byte[] tmpByte = new byte[tmpStrLen - 1];
tmpByte = Asc.GetBytes(strKey);
return tmpByte;
}
MD5
1 public static string EnMd5(string str)
2 {
3 string pwd = "";
4 MD5 md5 = MD5.Create();
5 //注意编码UTF8/Unicode
6 byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
7 for (int i = 0; i < s.Length; i++)
8 {
9 pwd = pwd + s[i].ToString("x2");
10 }
11 return pwd;
12 }
MD5(流Hash)
1 public static string GetStreamMD5(Stream stream)
2 {
3 MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
4
5 md5.ComputeHash(stream);
6
7 byte[] hash = md5.Hash;
8
9 StringBuilder result = new StringBuilder();
10
11 foreach (byte byt in hash)
12 {
13 result.Append(String.Format("{0:X1}", byt));
14 }
15
16 return result.ToString();
17 }
///
/// Base64解码
///
/// 需解码字符串
///
public static string Decode(string s)
{
byte[] outputb = Convert.FromBase64String(s);
return Encoding.Default.GetString(outputb);
}
///
/// Base64编码
///
/// 需编码字符串
///
public static string EncodeByUTF8(string s)
{
System.Text.Encoding encode = System.Text.Encoding.UTF8;
byte[] bytedata = encode.GetBytes(s);
return Convert.ToBase64String(bytedata, 0, bytedata.Length);
}
由于非对称加密算法的运行速度比对称加密算法的速度慢很多,当我们需要加密大量的数据时,建议采用对称加密算法,提高加解密速度。
对称加密算法不能实现签名,因此签名只能非对称算法。
由于对称加密算法的密钥管理是一个复杂的过程,密钥的管理直接决定着他的安全性,因此当数据量很小时,我们可以考虑采用非对称加密算法。
在实际的操作过程中,我们通常采用的方式是:采用非对称加密算法管理对称算法的密钥,然后用对称加密算法加密数据,这样我们就集成了两类加密算法的优点,既实现了加密速度快的优点,又实现了安全方便管理密钥的优点。
那采用多少位的密钥呢?
RSA建议采用1024位的数字,ECC建议采用160位,AES采用128为即可。
【算法大杂烩】常见算法的归类和总结——非对称加密算法
【Java----加密解密】第十章 五种对称加密算法总结
【对称与非对称加密算法】
【C#】常用的加密算法:MD5、Base64、SHA1、SHA256、HmacSHA256、DES、AES、RSA
【C#】加密算法[汇总]
国密(国产密码)SM2、SM3、SM4 C#实现