1、概述 加密在平时开发中也会经常用到,涉及登录、支付、接口设计等方面,可能都需要考虑到加密算法,加密算法分对称加密和非对称加密,对称加密使用的密钥只有一个,发送和接收双方都使用这个密钥对数据进行加密和解密,非对称加密算法,需要两个密钥,一个是公钥 (public key),另一个是私钥 (private key),如果使用公钥对数据 进行加密,只有用对应的私钥才能进行解密。如果使用私钥对数据 进行加密,只有用对应的公钥才能进行解密。
2、MD5 MD5一般用于对一段信息产生信息摘要即生成数字签名,以 防止被篡改。无论是多长的输入, MD5都会输出长度为128bits的一个串 (通常用16进制 表示为32个字符)。
java代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException; public class Md5Utils { private static final String UTF8 = "utf-8" ; public final static String encoder (String plainText) throws NoSuchAlgorithmException, UnsupportedEncodingException { byte [] bytes = plainText.getBytes(UTF8); MessageDigest mdInst = MessageDigest.getInstance("MD5" ); mdInst.update(bytes); byte [] md = mdInst.digest(); StringBuffer sb = new StringBuffer (); for (int i = 0 ; i < md.length; i++) { int val = ((int ) md[i]) & 0xff ; if (val < 16 ) { sb.append("0" ); } sb.append(Integer.toHexString(val)); } return sb.toString(); } }
3、SHA1 SHA1 是和 MD5 一样流行的 消息摘要算法,然而 SHA1 比 MD5 的 安全性更强。对于长度小于 2 ^ 64 位的消息,SHA1 会产生一个 160 位的 消息摘要。基于 MD5、SHA1 的信息摘要一般而言不可逆 ,可以被应用在检查 文件完整性 以及 数字签名 等场景。
java代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import java.security.MessageDigest; public final class Sha1Utils { private static final char [] HEX_DIGITS = {'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' }; private static String getFormattedText (byte [] bytes) { int len = bytes.length; StringBuilder buf = new StringBuilder (len * 2 ); for (int j = 0 ; j < len; j++) { buf.append(HEX_DIGITS[(bytes[j] >> 4 ) & 0x0f ]); buf.append(HEX_DIGITS[bytes[j] & 0x0f ]); } return buf.toString(); } public static String encode (String str) { if (str == null ) { return null ; } try { MessageDigest messageDigest = MessageDigest.getInstance("SHA1" ); messageDigest.update(str.getBytes()); return getFormattedText(messageDigest.digest()); } catch (Exception e) { throw new RuntimeException (e); } } }
4、RSA RSA 加密算法是目前比较优秀的公钥方案。RSA是第一个能同时用于加密和数字签名的算法,它能够抵抗到目前为止已知的 所有密码攻击,已被 ISO推荐为公钥数据加密标准。RSA 加密算法 基于一个十分简单的数论事实:将两个大 素数 相乘十分容易,但想要对其乘积进行 因式分解 却极其困难,因此可以将 乘积 公开作为 加密密钥。
java代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 import javax.crypto.Cipher;import java.security.*;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.Base64; public class RsaUtils { private static final String UTF8 = "UTF-8" ; public static RsaKeyPair generateKeyPair () throws NoSuchAlgorithmException { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA" ); keyPairGen.initialize(1024 , new SecureRandom ()); KeyPair keyPair = keyPairGen.generateKeyPair(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); String publicKeyString = new String (Base64.getEncoder().encode(publicKey.getEncoded())); String privateKeyString = new String (Base64.getEncoder().encode((privateKey.getEncoded()))); return new RsaKeyPair (publicKeyString, privateKeyString); } public static String encrypt (String plainText, String publicKey) throws Exception { byte [] decoded = Base64.getDecoder().decode(publicKey.getBytes(UTF8)); RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA" ).generatePublic(new X509EncodedKeySpec (decoded)); Cipher cipher = Cipher.getInstance("RSA" ); cipher.init(Cipher.ENCRYPT_MODE, pubKey); byte [] encodeBytes = Base64.getEncoder().encode(cipher.doFinal(plainText.getBytes(UTF8))); return new String (encodeBytes, UTF8); } public static String decrypt (String encryptText, String privateKey) throws Exception { byte [] inputByte = Base64.getDecoder().decode(encryptText.getBytes(UTF8)); byte [] decoded = Base64.getDecoder().decode(privateKey.getBytes(UTF8)); RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA" ).generatePrivate(new PKCS8EncodedKeySpec (decoded)); Cipher cipher = Cipher.getInstance("RSA" ); cipher.init(Cipher.DECRYPT_MODE, priKey); String outStr = new String (cipher.doFinal(inputByte)); return outStr; } private static class RsaKeyPair { private String publicKey; private String privateKey; public RsaKeyPair () { } public RsaKeyPair (String publicKey, String privateKey) { this .publicKey = publicKey; this .privateKey = privateKey; } public String getPublicKey () { return publicKey; } public void setPublicKey (String publicKey) { this .publicKey = publicKey; } public String getPrivateKey () { return privateKey; } public void setPrivateKey (String privateKey) { this .privateKey = privateKey; } } public static void main (String[] args) throws Exception { RsaKeyPair rsaKeyPair = generateKeyPair(); String message = "river106" ; System.out.println("随机生成的公钥为:" + rsaKeyPair.getPublicKey()); System.out.println("随机生成的私钥为:" + rsaKeyPair.getPrivateKey()); System.out.println("原始内容: " +message); String encryptText = encrypt(message, rsaKeyPair.getPublicKey()); System.out.println("加密后的字符串为:" + encryptText); String messageDe = decrypt(encryptText, rsaKeyPair.getPrivateKey()); System.out.println("解密后的字符串为:" + messageDe); } }
5、DES DES是 对称 的块加密算法 ,加解密 的过程是可逆的 。 DES 加密算法是一种 分组密码,以64位为分组对数据加密,它的密钥长度是56位,加密解密用同一算法。 DES 加密算法是对密钥进行保密,而公开算法,包括加密和解密算法。这样,只有掌握了和发送方相同密钥的人才能解读由DES加密算法加密的密文数据。因此,破译DES加密算法实际上就是搜索密钥的编码。对于56位长度的密钥来说,如果用穷举法来进行搜索的话,其运算次数为2^56次。
java代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import javax.crypto.Cipher;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;import java.util.Base64; public class DesUtils { private static final String UTF8 = "UTF-8" ; private static byte [] iv = {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 }; public static String encrypt (String plainText, String encryptKey) throws Exception { IvParameterSpec zeroIv = new IvParameterSpec (iv); SecretKeySpec key = new SecretKeySpec (encryptKey.getBytes(), "DES" ); Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding" ); cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv); byte [] encryptedData = cipher.doFinal(plainText.getBytes(UTF8)); return new String (Base64.getEncoder().encode(encryptedData), UTF8); } public static String decrypt (String encryptedText, String decryptKey) throws Exception { IvParameterSpec zeroIv = new IvParameterSpec (iv); SecretKeySpec key = new SecretKeySpec (decryptKey.getBytes(UTF8), "DES" ); Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding" ); cipher.init(Cipher.DECRYPT_MODE, key, zeroIv); byte decryptedData[] = cipher.doFinal(Base64.getDecoder().decode(encryptedText.getBytes(UTF8))); return new String (decryptedData, UTF8); } }
6、AES AES是 对称 的 块加密算法 ,加解密 的过程是 可逆的 。 AES 加密算法是密码学中的高级加密标准,该加密算法采用 对称分组密码体制,密钥长度的最少支持为128位、192位、256位,分组长度128位,算法应易于各种硬件和软件实现。这种加密算法是美国联邦政府采用的区块加密标准。 AES 本身就是为了取代 DES 的,AES 具有更好的 安全性、效率和灵活性。
java代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;import javax.crypto.spec.SecretKeySpec;import java.security.SecureRandom; public class AesUtils { public static String encrypt (String content, String password) throws Exception { StringBuilder sb = new StringBuilder (); KeyGenerator kgen = KeyGenerator.getInstance("AES" ); SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" ); secureRandom.setSeed(password.getBytes()); kgen.init(128 , secureRandom); SecretKey secretKey = kgen.generateKey(); byte [] enCodeFormat = secretKey.getEncoded(); SecretKeySpec key = new SecretKeySpec (enCodeFormat, "AES" ); Cipher cipher = Cipher.getInstance("AES" ); byte [] byteContent = content.getBytes("utf-8" ); cipher.init(Cipher.ENCRYPT_MODE, key); byte [] result = cipher.doFinal(byteContent); for (int i = 0 ; i < result.length; i++) { String hex = Integer.toHexString(result[i] & 0xFF ); if (hex.length() == 1 ) { hex = '0' + hex; } sb.append(hex.toUpperCase()); } return sb.toString(); } public static String decrypt (String content, String password) throws Exception { byte [] result = new byte [content.length() / 2 ]; for (int i = 0 ; i < content.length() / 2 ; i++) { int high = Integer.parseInt(content.substring(i * 2 , i * 2 + 1 ), 16 ); int low = Integer.parseInt(content.substring(i * 2 + 1 , i * 2 + 2 ), 16 ); result[i] = (byte ) (high * 16 + low); } KeyGenerator kgen = KeyGenerator.getInstance("AES" ); SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" ); secureRandom.setSeed(password.getBytes()); kgen.init(128 , secureRandom); SecretKey secretKey = kgen.generateKey(); byte [] enCodeFormat = secretKey.getEncoded(); SecretKeySpec key = new SecretKeySpec (enCodeFormat, "AES" ); Cipher cipher = Cipher.getInstance("AES" ); cipher.init(Cipher.DECRYPT_MODE, key); byte [] data = cipher.doFinal(result); return new String (data); } }