1.不可逆的算法
主要为MD5和SHA-1算法。(二者都不属于加密只能算作一种算法)
相同点:都是使用目前比较广泛的散列(Hash)函数,就是把任意长度的输入,变换成固定长度的输出,该输出就是散列值。计算的时候所有的数据都参与了运算,其中任何一个数据变化了都会导致计算出来的Hash值完全不同。(理论上来讲产生的密文都有可能产生碰撞)
不同点:MD5输出是128位的,SHA-1输出是160位的,MD5比SHA1运行速度快,SHA1比MD5强度高。MD5一般用于文件的校验,SHA-1主要使用于数字签名标准。
MD5使用:
1 1 public static String digest(String content){ 2 2 StringBuilder builder = new StringBuilder(); 3 3 try { 4 4 MessageDigest msgDitest = MessageDigest.getInstance("MD5"); 5 5 msgDitest.update(content.getBytes()); 6 6 byte[] digests = msgDitest.digest(); 7 7 //将每个字节转为16进制 8 8 for (int i=0;i<digests.length;i++){ 9 9 // TODO: 2019/11/10 需要再了解一下 1010 builder.append(Integer.toHexString(digests[i] & 0xff +8));//+8为加盐操作 1111 } 1212 } catch (NoSuchAlgorithmException e) { 1313 e.printStackTrace(); 1414 } 1515 return builder.toString(); 1616 }
SHA-1使用:
1 1 public static String sha1Digest(String content){ 2 2 StringBuilder builder = new StringBuilder(); 3 3 try { 4 4 MessageDigest msgDitest = MessageDigest.getInstance("SHA-1"); 5 5 msgDitest.update(content.getBytes()); 6 6 byte[] digests = msgDitest.digest(); 7 7 //将每个字节转为16进制 8 8 for (int i=0;i<digests.length;i++){ 9 9 // TODO: 2019/11/10 再了解一下 1010 builder.append(Integer.toHexString(digests[i] & 0xff +8));//+8为加盐操作 1111 } 1212 } catch (NoSuchAlgorithmException e) { 1313 e.printStackTrace(); 1414 } 1515 return builder.toString(); 1616 }
2.可逆算法
其中可逆算法按照密钥的数量和加密规则又分为对称加密和非对称加密。
(1)对称加密
密钥可以自己指定,只有一把密钥。常用的对称加密算法有DES和AES两种。对称加密的速度快,但是缺点是安全性低,因为只要密钥暴漏,数据就可以被解密。
AES加密解密使用:

1 1 package com.cn; 2 2 3 3 import sun.misc.BASE64Decoder; 4 4 import sun.misc.BASE64Encoder; 5 5 6 6 import javax.crypto.*; 7 7 import javax.crypto.spec.SecretKeySpec; 8 8 import java.io.IOException; 9 9 import java.io.UnsupportedEncodingException; 10 10 import java.security.InvalidKeyException; 11 11 import java.security.NoSuchAlgorithmException; 12 12 import java.security.SecureRandom; 13 13 import java.util.Scanner; 14 14 15 15 public class SymmetricEncoder { 16 16 /* 17 17 * 加密 18 18 * 1.构造密钥生成器 19 19 * 2.根据ecnodeRules规则初始化密钥生成器 20 20 * 3.产生密钥 21 21 * 4.创建和初始化密码器 22 22 * 5.内容加密 23 23 * 6.返回字符串 24 24 */ 25 25 public static String AESEncode(String encodeRules,String content){ 26 26 try { 27 27 //1.构造密钥生成器,指定为AES算法,不区分大小写 28 28 KeyGenerator keygen=KeyGenerator.getInstance("AES"); 29 29 //2.根据ecnodeRules规则初始化密钥生成器 30 30 //生成一个128位的随机源,根据传入的字节数组 31 31 keygen.init(128, new SecureRandom(encodeRules.getBytes())); 32 32 //3.产生原始对称密钥 33 33 SecretKey original_key=keygen.generateKey(); 34 34 //4.获得原始对称密钥的字节数组 35 35 byte [] raw=original_key.getEncoded(); 36 36 //5.根据字节数组生成AES密钥 37 37 SecretKey key=new SecretKeySpec(raw, "AES"); 38 38 //6.根据指定算法AES自成密码器 39 39 Cipher cipher=Cipher.getInstance("AES"); 40 40 //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY 41 41 cipher.init(Cipher.ENCRYPT_MODE, key); 42 42 //8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码 43 43 byte [] byte_encode=content.getBytes("utf-8"); 44 44 //9.根据密码器的初始化方式--加密:将数据加密 45 45 byte [] byte_AES=cipher.doFinal(byte_encode); 46 46 //10.将加密后的数据转换为字符串 47 47 //这里用Base64Encoder中会找不到包 48 48 //解决办法: 49 49 //在项目的Build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。 50 50 String AES_encode=new String(new BASE64Encoder().encode(byte_AES)); 51 51 //11.将字符串返回 52 52 return AES_encode; 53 53 } catch (NoSuchAlgorithmException e) { 54 54 e.printStackTrace(); 55 55 } catch (NoSuchPaddingException e) { 56 56 e.printStackTrace(); 57 57 } catch (InvalidKeyException e) { 58 58 e.printStackTrace(); 59 59 } catch (IllegalBlockSizeException e) { 60 60 e.printStackTrace(); 61 61 } catch (BadPaddingException e) { 62 62 e.printStackTrace(); 63 63 } catch (UnsupportedEncodingException e) { 64 64 e.printStackTrace(); 65 65 } 66 66 67 67 //如果有错就返加null 68 68 return null; 69 69 } 70 70 /* 71 71 * 解密 72 72 * 解密过程: 73 73 * 1.同加密1-4步 74 74 * 2.将加密后的字符串反纺成byte[]数组 75 75 * 3.将加密内容解密 76 76 */ 77 77 public static String AESDncode(String encodeRules,String content){ 78 78 try { 79 79 //1.构造密钥生成器,指定为AES算法,不区分大小写 80 80 KeyGenerator keygen=KeyGenerator.getInstance("AES"); 81 81 //2.根据ecnodeRules规则初始化密钥生成器 82 82 //生成一个128位的随机源,根据传入的字节数组 83 83 keygen.init(128, new SecureRandom(encodeRules.getBytes())); 84 84 //3.产生原始对称密钥 85 85 SecretKey original_key=keygen.generateKey(); 86 86 //4.获得原始对称密钥的字节数组 87 87 byte [] raw=original_key.getEncoded(); 88 88 //5.根据字节数组生成AES密钥 89 89 SecretKey key=new SecretKeySpec(raw, "AES"); 90 90 //6.根据指定算法AES自成密码器 91 91 Cipher cipher=Cipher.getInstance("AES"); 92 92 //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY 93 93 cipher.init(Cipher.DECRYPT_MODE, key); 94 94 //8.将加密并编码后的内容解码成字节数组 95 95 byte [] byte_content= new BASE64Decoder().decodeBuffer(content); 96 96 /* 97 97 * 解密 98 98 */ 99 99 byte [] byte_decode=cipher.doFinal(byte_content); 100100 String AES_decode=new String(byte_decode,"utf-8"); 101101 return AES_decode; 102102 } catch (NoSuchAlgorithmException e) { 103103 e.printStackTrace(); 104104 } catch (NoSuchPaddingException e) { 105105 e.printStackTrace(); 106106 } catch (InvalidKeyException e) { 107107 e.printStackTrace(); 108108 } catch (IOException e) { 109109 e.printStackTrace(); 110110 } catch (IllegalBlockSizeException e) { 111111 e.printStackTrace(); 112112 } catch (BadPaddingException e) { 113113 e.printStackTrace(); 114114 } 115115 116116 //如果有错就返加null 117117 return null; 118118 } 119119 120120 public static void main(String[] args) { 121121 SymmetricEncoder se=new SymmetricEncoder(); 122122 Scanner scanner=new Scanner(System.in); 123123 /* 124124 * 加密 125125 */ 126126 System.out.println("使用AES对称加密,请输入加密的规则"); 127127 String encodeRules=scanner.next(); 128128 System.out.println("请输入要加密的内容:"); 129129 String content = scanner.next(); 130130 System.out.println("根据输入的规则"+encodeRules+"加密后的密文是:"+se.AESEncode(encodeRules, content)); 131131 132132 /* 133133 * 解密 134134 */ 135135 System.out.println("使用AES对称解密,请输入加密的规则:(须与加密相同)"); 136136 encodeRules=scanner.next(); 137137 System.out.println("请输入要解密的内容(密文):"); 138138 content = scanner.next(); 139139 System.out.println("根据输入的规则"+encodeRules+"解密后的明文是:"+se.AESDncode(encodeRules, content)); 140140 } 141141 }
View Code
DES加密解密使用:

1 1 package com.cn; 2 2 3 3 import javax.crypto.*; 4 4 import javax.crypto.spec.DESKeySpec; 5 5 import java.security.InvalidAlgorithmParameterException; 6 6 import java.security.InvalidKeyException; 7 7 import java.security.NoSuchAlgorithmException; 8 8 import java.security.SecureRandom; 9 9 import java.security.spec.InvalidKeySpecException; 1010 1111 public class DESUtil { 1212 public static byte[] encode(String mes) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidKeySpecException, InvalidAlgorithmParameterException { 1313 SecureRandom random = new SecureRandom(); 1414 // TODO: 2019/11/10 密钥长度应该是要大于8 1515 DESKeySpec desKey = new DESKeySpec("123abc123".getBytes()); 1616 //创建一个密匙工厂,然后用它把DESKeySpec转换成 1717 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 1818 SecretKey securekey = keyFactory.generateSecret(desKey); 1919 //Cipher对象实际完成加密操作 2020 Cipher cipher = Cipher.getInstance("DES"); 2121 //用密匙初始化Cipher对象 2222 cipher.init(Cipher.ENCRYPT_MODE, securekey, random); 2323 return cipher.doFinal(mes.getBytes()); 2424 } 2525 2626 public static byte[] decode(byte[] encodeBytes) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException { 2727 // DES算法要求有一个可信任的随机数源 2828 SecureRandom random = new SecureRandom(); 2929 // 创建一个DESKeySpec对象 3030 DESKeySpec desKey = new DESKeySpec("123abc123".getBytes()); 3131 // 创建一个密匙工厂 3232 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 3333 // 将DESKeySpec对象转换成SecretKey对象 3434 SecretKey securekey = keyFactory.generateSecret(desKey); 3535 // Cipher对象实际完成解密操作 3636 Cipher cipher = Cipher.getInstance("DES"); 3737 // 用密匙初始化Cipher对象 3838 cipher.init(Cipher.DECRYPT_MODE, securekey, random); 3939 // 真正开始解密操作 4040 return cipher.doFinal(encodeBytes); 4141 } 4242 }
View Code
(2)非对称加密
常见的非对称加密算法是RSA;他有两把密钥,且是由程序生成的,不能自己指定;特点是加密速度比较慢,但是安全性比较高;加密和解密的规则是:公钥加密只能私钥解密,私钥加密只能公钥解密。

1 1 package com.cn; 2 2 3 3 import android.util.Base64; 4 4 5 5 import javax.crypto.Cipher; 6 6 import java.security.*; 7 7 import java.security.interfaces.RSAPrivateKey; 8 8 import java.security.interfaces.RSAPublicKey; 9 9 import java.security.spec.PKCS8EncodedKeySpec; 1010 import java.security.spec.X509EncodedKeySpec; 1111 import java.util.HashMap; 1212 import java.util.Map; 1313 1414 public class RSAUtil { 1515 private static Map<Integer, String> keyMap = new HashMap<Integer, String>(); //用于封装随机产生的公钥与私钥 1616 public static void main(String[] args) throws Exception { 1717 //生成公钥和私钥 1818 genKeyPair(); 1919 //加密字符串 2020 String message = "abc12301230"; 2121 System.out.println("随机生成的公钥为:" + keyMap.get(0)); 2222 System.out.println("随机生成的私钥为:" + keyMap.get(1)); 2323 String messageEn = encrypt(message,keyMap.get(0)); 2424 System.out.println(message + "\t加密后的字符串为:" + messageEn); 2525 String messageDe = decrypt(messageEn,keyMap.get(1)); 2626 System.out.println("还原后的字符串为:" + messageDe); 2727 } 2828 2929 /** 3030 * 随机生成密钥对 3131 * @throws NoSuchAlgorithmException 3232 */ 3333 public static void genKeyPair() throws NoSuchAlgorithmException { 3434 // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象 3535 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); 3636 // 初始化密钥对生成器,密钥大小为96-1024位 3737 keyPairGen.initialize(1024,new SecureRandom()); 3838 // 生成一个密钥对,保存在keyPair中 3939 KeyPair keyPair = keyPairGen.generateKeyPair(); 4040 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥 4141 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥 4242 String publicKeyString = new String(Base64.encode(publicKey.getEncoded(), 0)); 4343 // 得到私钥字符串 4444 String privateKeyString = new String(Base64.encode(privateKey.getEncoded(), 0)); 4545 // 将公钥和私钥保存到Map 4646 keyMap.put(0,publicKeyString); //0表示公钥 4747 keyMap.put(1,privateKeyString); //1表示私钥 4848 } 4949 /** 5050 * RSA公钥加密 5151 * 5252 * @param str 5353 * 加密字符串 5454 * @param publicKey 5555 * 公钥 5656 * @return 密文 5757 * @throws Exception 5858 * 加密过程中的异常信息 5959 */ 6060 public static String encrypt(String str, String publicKey) throws Exception{ 6161 //base64编码的公钥 6262 byte[] decoded = Base64.decode(publicKey, 0); 6363 RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded)); 6464 //RSA加密 6565 Cipher cipher = Cipher.getInstance("RSA"); 6666 cipher.init(Cipher.ENCRYPT_MODE, pubKey); 6767 String outStr = new String(Base64.encode(cipher.doFinal(str.getBytes("UTF-8")), 0)); 6868 return outStr; 6969 } 7070 7171 /** 7272 * RSA私钥解密 7373 * 7474 * @param str 7575 * 加密字符串 7676 * @param privateKey 7777 * 私钥 7878 * @return 铭文 7979 * @throws Exception 8080 * 解密过程中的异常信息 8181 */ 8282 public static String decrypt(String str, String privateKey) throws Exception{ 8383 //64位解码加密后的字符串 8484 byte[] inputByte = Base64.decode(str.getBytes(), 0); 8585 //base64编码的私钥 8686 byte[] decoded = Base64.decode(privateKey, 0); 8787 RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); 8888 //RSA解密 8989 Cipher cipher = Cipher.getInstance("RSA"); 9090 cipher.init(Cipher.DECRYPT_MODE, priKey); 9191 String outStr = new String(cipher.doFinal(inputByte)); 9292 return outStr; 9393 } 9494 }
View Code
// TODO AES加密模式, padding填充模式??
参考资料:https://www.cnblogs.com/yegong0214/p/6498409.html
https://blog.csdn.net/u011897782/article/details/81163387
https://blog.csdn.net/joshho/article/details/88716314
https://www.cnblogs.com/jying/p/9511247.html
https://blog.csdn.net/qy20115549/article/details/83105736
// TODO