////// AES对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB),这三种的区别,主要来自于密钥的长度,16位密钥=128位,24位密钥=192位,32位密钥=256位 /// 检验密钥是否有效长度【16|24|32】 /// /// 密钥 ///bool private static bool AesCheckKey(string key) { if (string.IsNullOrWhiteSpace(key)) return false; if (16.Equals(key.Length) || 24.Equals(key.Length) || 32.Equals(key.Length)) return true; else return false; } #region 参数是string类型的 ////// AES加密 参数:string /// /// 源字符串 /// 密钥 /// 是否转64进制 /// 运算模式 /// 填充模式 /// 编码类型 ///加密后的字符串 public static string AesEncrypt(string source, string key, bool base64 = false, CipherMode model = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding encoding = null) { if (string.IsNullOrWhiteSpace(source)) return null; if (!AesCheckKey(key)) return source; if (encoding == null) encoding = Encoding.UTF8; using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider()) { aesProvider.Key = encoding.GetBytes(key); aesProvider.Mode = model; aesProvider.Padding = padding; //aesProvider.KeySize = 128; //aesProvider.BlockSize = 128; using (ICryptoTransform cryptoTransform = aesProvider.CreateEncryptor()) { byte[] toEncryptArray = encoding.GetBytes(source); byte[] resultArray = cryptoTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); aesProvider.Clear(); //return Convert.ToBase64String(resultArray, 0, resultArray.Length); return base64 ? Convert.ToBase64String(resultArray) : byteToHexString(resultArray); } } //RijndaelManaged rijndaelCipher = new RijndaelManaged(); //rijndaelCipher.Mode = CipherMode.ECB; //rijndaelCipher.Padding = PaddingMode.PKCS7; //rijndaelCipher.KeySize = 128; //rijndaelCipher.BlockSize = 128; //byte[] pwdBytes = System.Text.Encoding.UTF8.GetBytes(key); //byte[] keyBytes = new byte[16]; //int len = pwdBytes.Length; //if (len > keyBytes.Length) len = keyBytes.Length; //System.Array.Copy(pwdBytes, keyBytes, len); //rijndaelCipher.Key = keyBytes; ////加密初始化向量 //string iv = " "; //byte[] ivBytes = System.Text.Encoding.UTF8.GetBytes(iv); //rijndaelCipher.IV = new byte[16]; //ICryptoTransform transform = rijndaelCipher.CreateEncryptor(); //byte[] plainText = System.Text.Encoding.UTF8.GetBytes(source); //byte[] cipherBytes = transform.TransformFinalBlock(plainText, 0, plainText.Length); //return byteToHexString(cipherBytes);// Convert.ToBase64String(cipherBytes); } ////// AES解密 参数:string /// /// 源字符串 /// 密钥 /// 是否转64进制 /// 运算模式 /// 填充模式 /// 编码类型 ///解密后的字符串 public static string AesDecrypt(string source, string key, bool base64 = false, CipherMode model = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding encoding = null) { if (string.IsNullOrWhiteSpace(source)) return null; if (!AesCheckKey(key)) return source; if (encoding == null) encoding = Encoding.UTF8; using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider()) { aesProvider.Key = encoding.GetBytes(key); aesProvider.Mode = model; aesProvider.Padding = padding; //aesProvider.KeySize = 128; //aesProvider.BlockSize = 128; using (ICryptoTransform cryptoTransform = aesProvider.CreateDecryptor()) { byte[] toEncryptArray = base64 == true ? Convert.FromBase64String(source) : stringToHexByte(source); byte[] resultArray = cryptoTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); aesProvider.Clear(); return encoding.GetString(resultArray); } } } #endregion ////// 字节数组转16进制字符串 /// /// ///public static string byteToHexString(byte[] bytes) { string returnStr = ""; if (bytes != null) { for (int i = 0; i < bytes.Length; i++) { returnStr += bytes[i].ToString("X2"); } } return returnStr; } /// /// 将16进制字符串转换为字节数组 /// /// ///private static byte[] stringToHexByte(string hexString) { hexString = hexString.Replace(" ", ""); if ((hexString.Length % 2) != 0) hexString += " "; byte[] returnBytes = new byte[hexString.Length / 2]; for (int i = 0; i < returnBytes.Length; i++) returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); return returnBytes; } #region 参数是byte[]类型的 /// /// AES加密 参数:byte[] /// /// 源字符字节组 /// 密钥 /// 运算模式 /// 填充模式 /// 编码类型 ///加密后的字符字节组 public static byte[] AesEncrypt(byte[] source, string key, CipherMode model = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding encoding = null) { if (source == null) return null; if (!AesCheckKey(key)) return source; if (encoding == null) encoding = Encoding.UTF8; byte[] bKey = encoding.GetBytes(key); byte[] cryptograph = null; //加密后的密文 Rijndael Aes = Rijndael.Create(); Aes.Key = bKey; //开辟一块内存流 using (MemoryStream Memory = new MemoryStream()) { //把内存流对象包装成加密流对象 using (CryptoStream Encryptor = new CryptoStream(Memory, Aes.CreateEncryptor(), CryptoStreamMode.Write)) { //明文数据写入加密流 Encryptor.Write(source, 0, source.Length); Encryptor.FlushFinalBlock(); cryptograph = Memory.ToArray(); } } return cryptograph; } ////// AES解密 参数:byte[] /// /// 源字符字节组 /// 密钥 /// 运算模式 /// 填充模式 /// 编码类型 ///解密后的字符字节组 public static byte[] AesDecrypt(byte[] source, string key, CipherMode model = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding encoding = null) { if (source == null) return null; if (!AesCheckKey(key)) return source; if (encoding == null) encoding = Encoding.UTF8; byte[] bKey = encoding.GetBytes(key); byte[] original = null; //解密后的明文 Rijndael Aes = Rijndael.Create(); //开辟一块内存流,存储密文 using (MemoryStream Memory = new MemoryStream(source)) { //把内存流对象包装成加密流对象 using (CryptoStream Decryptor = new CryptoStream(Memory, Aes.CreateDecryptor(bKey, null), CryptoStreamMode.Read)) { //明文存储区 using (MemoryStream originalMemory = new MemoryStream()) { byte[] Buffer = new byte[1024]; int readBytes = 0; while ((readBytes = Decryptor.Read(Buffer, 0, Buffer.Length)) > 0) { originalMemory.Write(Buffer, 0, readBytes); } original = originalMemory.ToArray(); } } } return original; } #endregion ////// 对字符串SHA1加密 /// /// 源字符串 /// 编码类型 ///加密后的十六进制字符串 public static string Sha1Encrypt(string source, Encoding encoding = null) { if (encoding == null) encoding = Encoding.UTF8; // 第一种方式 byte[] byteArray = encoding.GetBytes(source); using (HashAlgorithm hashAlgorithm = new SHA1CryptoServiceProvider()) { byteArray = hashAlgorithm.ComputeHash(byteArray); StringBuilder stringBuilder = new StringBuilder(256); foreach (byte item in byteArray) { stringBuilder.AppendFormat("{0:x2}", item); } hashAlgorithm.Clear(); return stringBuilder.ToString(); } //// 第二种方式 //using (SHA1 sha1 = SHA1.Create()) //{ // byte[] hash = sha1.ComputeHash(encoding.GetBytes(source)); // StringBuilder stringBuilder = new StringBuilder(); // for (int index = 0; index < hash.Length; ++index) // stringBuilder.Append(hash[index].ToString("x2")); // sha1.Clear(); // return stringBuilder.ToString(); //} } ////// 对字符串MD5加密 /// /// 源字符串 /// 编码类型 ///加密后的十六进制字符串 public static string Md5Encrypt(string source, Encoding encoding = null) { if (encoding == null) encoding = Encoding.UTF8; byte[] byteArray = encoding.GetBytes(source); using (HashAlgorithm hashAlgorithm = new MD5CryptoServiceProvider()) { byteArray = hashAlgorithm.ComputeHash(byteArray); StringBuilder stringBuilder = new StringBuilder(); foreach (byte item in byteArray) { stringBuilder.AppendFormat("{0:x2}", item); } hashAlgorithm.Clear(); return stringBuilder.ToString(); } }
AES加密方式中
在PKCS5Padding中,明确定义Block的大小是8位,而在PKCS7Padding定义中,对于块的大小是不确定的,可以在1-255之间(块长度超出255的尚待研究),填充值的算法都是一样的:
value=k - (l mod k) ,K=块大小,l=数据长度,如果l=8, 则需要填充额外的8个byte的8
在.net中,例如TripleDESCryptoServiceProvider ,默认BlockSize=64bits=8bytes,所以在这种情况下在PKCS5Padding=PKCS7Padding。
如果在C#中自己定义了一个不是64bits的加密块大小,同时使用PKCS7Padding,那么在java中使用JDK标准的PKCS5Padding就不能解密了。