一、基本介绍
1、加密类型(对称加密/非对称加密)
对称加密:简单来说就是加密与解密用的是同一把秘钥。
非对称加密:加密用的是一把秘钥,解密的时候用的是另一把秘钥(例如一把私钥,一把公钥)。
2、加密方式(流加密,分组加密)
流加密:就是将加密的内容每个元素都用秘钥一个一个去处理。
分组加密:将加密的内容分组,用秘钥按组去区分。所以如果按分组去处理的话,就需要进行填充,因为可能最后的一组位数不够分一块。
3、常见的对称加密算法
DES:Data Encryption Standard (数据加密标准),分组加密,秘钥是8位
AES:Advanced Encryption Standard(高级加密标准),是DES的升级版本(所以一般是用这个),不过其的秘钥需要16位。
4、常见的加密模式
ECB:Electronic codebook, 电子密码本. 将加密的消息按照块划分,对每个块进行独立加密。
CBC:Cipher-block chaining, 密码块链接. 每个明文块先与前一个密文块进行异或后,再进行加密。这种方法,每个密文块都依赖于它前面的所有明文块。(所以加密第一块的实时就需要给其一个自己定义的初始向量参数)。
所以EBC能并行处理,CBC不能,但CBC更安全。
5、常见的块加密的填充方式
NoPadding:不填充,就是说不进行填充,所以待加密的内容刚好需要为划分的块的大小的倍数。例如DES就需要为8 byte的倍数,AES就需要为16 byte的位数。
PKCS7Padding、PKCS5Padding、ZeroPadding:可以看下这篇文章,这里需要注意的是如果是ZeroPadding,因为其是用0去填充的,所以当分的最后一块的最后元素也有0的话就可能产生问题,所以直接根据密文的话就区分不了。
6、base64
介绍:我们知道加密的密文byte可能会对应到ascii表的任何映射,有些都不是可读的,可能有些都是具有特殊含义的(传输过程可能产生问题),所以我们需要将其转换为可读的、可打印的。所以base64的操作就是将byte都映射到用A-Z、a-z、0-9、+、/去标识,然后到需要使用的时候再将其转换为原来的内容。
转换原理:三个byte为一组,就是3*8=24。然后base64再将这个24以4*6的方式组合,划分为四组,每组6bit最高的两位用0填充形成一个byte(00111111=63 -- 0-63总共64种组合),也就是将3个byte转换为4个byte。不足形成一个组的剩下的用'='去填充。
案例代码:
// 3*8=24 为3个字符 3*n不需要填充 String content1 = "ABC"; String encode1 = Base64.encode(content1.getBytes()); // 4*8 = 32 所以对打印4个字符 System.out.println(encode1); //2*8 = 16 为两个字符 String content2 = "AB"; String encode2 = Base64.encode(content2.getBytes()); //所以会填充一个= System.out.println(encode2);
二、AES/DES案例代码
1、DES算法(加密模式为ECB)
1、main方法
public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, Base64DecodingException, InvalidAlgorithmParameterException { //对称加密的算法 String algorithm = "DES"; //秘钥 String key = "12345678"; //对称加密的类型信息 String algorithmType = "DES"; //原文 String content = "明文"; //EBC模式 String encryptionContent = encryptionECB(algorithm, key, algorithmType, content); System.out.println("ECB Encryption Code : " + encryptionContent); byte[] decryptionBytes = decryptionECB(algorithm,key,algorithmType,encryptionContent); System.out.println("ECB Decryption Code : " + new String(decryptionBytes).toString()); }
2、encryptionECB方法
/** * 加密操作 * @param algorithm 对称加密的算法 DES/AES * @param key 秘钥 8位 * @param algorithmType 对称加密的类型信息 * 设置规则:算法/模式/填充 如果只写算法如DES或者AES,则默认是 (DES/AES)/ECB/PKCS5Padding * @param content 原文 * ............ */ public static String encryptionECB(String algorithm,String key,String algorithmType,String content) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException { //加密操作的对象 Cipher cipher = Cipher.getInstance(algorithmType); //加密规则 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithm); // 参数1:进行init的类型:加密/解密=ENCRYPT/DECRYPT,参数2加密规则 cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec); //加密操作 byte[] bytes = cipher.doFinal(content.getBytes()); System.out.print("doFinalChars:"); for (int i = 0; i < bytes.length; i++) { System.out.print((char)bytes[i]); } System.out.println(); //进行Base64的操作:让密文具有可读性,在解密的时候也需要进行Base64的解密 // (Base64不是一种加密操作,只是增加可读写) // (也可以不进行base64操作,同样在解密的时候也不需要解析base64的操作) String encodeContent = Base64.encode(bytes); return encodeContent; }
3、decryptionECB
public static byte[] decryptionECB(String algorithm,String key,String algorithmType,String encryptContent) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, Base64DecodingException { //Base64的解密 byte[] decryptionCode = Base64.decode(encryptContent.getBytes()); //加密操作的对象 Cipher cipher = Cipher.getInstance(algorithmType); //加密规则 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithm); // 参数1:进行init的类型:加密/解密=ENCRYPT/DECRYPT,参数2加密规则 cipher.init(Cipher.DECRYPT_MODE,secretKeySpec); //加密操作 byte[] bytes = cipher.doFinal(decryptionCode); return bytes; }
2、AES算法(加密模式为CBC)
这里由于我们使用的是CBC模式,所以需要多一个初始向量参数。下面代码多了一个创建IvParameterSpec的过程
1、main方法
public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, Base64DecodingException, InvalidAlgorithmParameterException { //原文 String content = "明文"; //CBC模式 String algorithmCBC = "AES"; String keyAES = "1234567812345678"; String algorithmTypeCBC = "AES/CBC/PKCS5Padding"; String ivParameter = "8765432187654321"; String encryptionCBCContent = encryptionCBC(algorithmCBC, keyAES, ivParameter, algorithmTypeCBC, content); System.out.println("CBC Encryption Code : " + encryptionCBCContent); byte[] decryptionCBC = decryptionCBC(algorithmCBC, keyAES, ivParameter, algorithmTypeCBC, encryptionCBCContent); System.out.println("CBC Decryption Code : " + new String(decryptionCBC).toString()); }
2、encryptionCBC
/** * @param algorithm 对称加密的算法 DES/AES * @param key 秘钥 16位 * @param ivParameter IV向量 16位 * @param algorithmType 对称加密的类型信息 * @param content 原文 * ....... */ public static String encryptionCBC(String algorithm,String key,String ivParameter,String algorithmType,String content) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException { //加密操作的对象 Cipher cipher = Cipher.getInstance(algorithmType); //加密规则 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithm); //创建IV向量 IvParameterSpec ivParameterSpec = new IvParameterSpec(ivParameter.getBytes()); // 参数1:进行init的类型:加密/解密=ENCRYPT/DECRYPT,参数2加密规则 cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec,ivParameterSpec); //加密操作 byte[] bytes = cipher.doFinal(content.getBytes()); //进行Base64的操作:让密文具有可读性,在解密的时候也需要进行Base64的解密 // (Base64不是一种加密操作,只是增加可读写) // (也可以不进行base64操作,同样在解密的时候也不需要解析base64的操作) String encodeContent = Base64.encode(bytes); return encodeContent; }
3、decryptionCBC
public static byte[] decryptionCBC(String algorithm,String key,String ivParameter,String algorithmType,String encryptContent) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, Base64DecodingException, InvalidAlgorithmParameterException { //Base64的解密 byte[] decryptionCode = Base64.decode(encryptContent.getBytes()); //加密操作的对象 Cipher cipher = Cipher.getInstance(algorithmType); //加密规则 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithm); //创建IV向量 IvParameterSpec ivParameterSpec = new IvParameterSpec(ivParameter.getBytes()); // 参数1:进行init的类型:加密/解密=ENCRYPT/DECRYPT,参数2加密规则 cipher.init(Cipher.DECRYPT_MODE,secretKeySpec,ivParameterSpec); //加密操作 byte[] bytes = cipher.doFinal(decryptionCode); return bytes; }
三:数字摘要
1、数字摘要的介绍与意义
1、介绍
数字摘要就是将任意长度的消息变成固定长度的短消息,一般用散列算法去处理,例如:MD5、SHA-1、SHA-256、SHA-512,这些都是散列算法,对于它们产生的结果来说:主要的区别就是会产生不同bit长度的结果,还有就是安全性问题,例如SHA-512这个长度比较长所以相对来说要碰撞就更不容易。
2、意义
其作用主要来说就是用来看这个消息的内容有没有被修改,一个消息即使做了很少的改动,最终产生的结果也会很大。
2、案例代码
public static void main(String[] args) throws NoSuchAlgorithmException { String content = "明文"; String algorithm = "MD5"; // MD5/SHA-1/SHA-256/SHA-512 MessageDigest messageDigest = MessageDigest.getInstance(algorithm); //数字摘要的byte byte[] digestContext = messageDigest.digest(content.getBytes()); //一般是用16进制进行展示,所以需要进行转换16进制 // 4 bit 表示一个16进制数 4*32 = 128 & 8*16 = 128 String hexTo16 = hexTo16(digestContext); System.out.println(hexTo16); } public static String hexTo16(byte[] bytes){ StringBuffer stringBuffer = new StringBuffer(); for (byte byteCode : bytes) { //为两个长度 String hexString = Integer.toHexString(byteCode & 0xff); //由于产生的hexString ,如果是05这种,hexString没有前面的0,所以需要加上 if (hexString.length() == 1) { stringBuffer.append("0"); } stringBuffer.append(hexString); } return stringBuffer.toString(); }
其进行签名产生的结果总共16byte:
然后转换为16进制后的最终结果是:,长度为32
3、Integer.toHexString方法的简单介绍
简单来说,这个方法就是将byte(1个byte :8bit,4bit表示一个16进制的数)写成两个16进制数字符,会省略前面的0
案例代码:
byte byte1 = (byte)12; String toHexString1 = Integer.toHexString(byte1); System.out.println("toHexString1: " + toHexString1); byte byte2 = (byte)16; String toHexString2 = Integer.toHexString(byte2); System.out.println("toHexString2: " + toHexString2);
产生的结果:。