Java之加密演算法
阿新 • • 發佈:2018-11-04
加密演算法主要分為對稱加密、非對稱加密、Hash加密。
一、何為對稱加密?
對稱加密是指對稱密碼編碼技術,它的特點是檔案加密和解密使用相同的金鑰加密。
對稱機密的金鑰一般小於256bit。因為就金鑰而言,如果加密的金鑰越大,則其計算的複雜度越高,所需要的時間越長,而如果使用的金鑰較小,則很容易破解,所以金鑰的大小需根據業務需求去選擇。
通常,加密的演算法有:DES、3DES、Blowfish、IDEA、RC4、RC5、RC6和AES 。
程式碼段引用:https://blog.csdn.net/chengbinbbs/article/details/78640589
public class DESUtil { private static final String KEY_ALGORITHM = "DES"; private static final String DEFAULT_CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";//預設的加密演算法 /** * DES 加密操作 * * @param content 待加密內容 * @param key 加密金鑰 * @return 返回Base64轉碼後的加密資料 */ public static String encrypt(String content, String key) { try { Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 建立密碼器 byte[] byteContent = content.getBytes("utf-8"); cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));// 初始化為加密模式的密碼器 byte[] result = cipher.doFinal(byteContent);// 加密 return Base64.encodeBase64String(result);//通過Base64轉碼返回 } catch (Exception ex) { Logger.getLogger(DESUtil.class.getName()).log(Level.SEVERE, null, ex); } return null; } /** * DES 解密操作 * * @param content * @param key * @return */ public static String decrypt(String content, String key) { try { //例項化 Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM); //使用金鑰初始化,設定為解密模式 cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key)); //執行操作 byte[] result = cipher.doFinal(Base64.decodeBase64(content)); return new String(result, "utf-8"); } catch (Exception ex) { Logger.getLogger(DESUtil.class.getName()).log(Level.SEVERE, null, ex); } return null; } /** * 生成加密祕鑰 * * @return */ private static SecretKeySpec getSecretKey(final String key) { //返回生成指定演算法金鑰生成器的 KeyGenerator 物件 KeyGenerator kg = null; try { kg = KeyGenerator.getInstance(KEY_ALGORITHM); //DES 要求金鑰長度為 56 kg.init(56, new SecureRandom(key.getBytes())); //生成一個金鑰 SecretKey secretKey = kg.generateKey(); return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 轉換為DES專用金鑰 } catch (NoSuchAlgorithmException ex) { Logger.getLogger(DESUtil.class.getName()).log(Level.SEVERE, null, ex); } return null; } public static void main(String[] args) { String content = "hello,您好"; String key = "[email protected]*^hsff%dfs$r344&df8543*er"; System.out.println("content:" + content); String s1 = DESUtil.encrypt(content, key); System.out.println("s1:" + s1); System.out.println("s2:"+ DESUtil.decrypt(s1, key)); } }
二、非對稱加密
何為非對稱加密?
非對稱加密是指加密和解密使用兩個不同的金鑰
通常,非對稱加密的演算法有:RSA、ECC(移動裝置用)、Diffie-Hellman、El Gamal、DSA(數字簽名用)
程式碼段引用:https://blog.csdn.net/chengbinbbs/article/details/78640589
public class RSAUtils { /** * 加密演算法RSA */ public static final String KEY_ALGORITHM = "RSA"; /** * 簽名演算法 */ public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; /** * 獲取公鑰的key */ private static final String PUBLIC_KEY = "RSAPublicKey"; /** * 獲取私鑰的key */ private static final String PRIVATE_KEY = "RSAPrivateKey"; /** * RSA最大加密明文大小 */ private static final int MAX_ENCRYPT_BLOCK = 117; /** * RSA最大解密密文大小 */ private static final int MAX_DECRYPT_BLOCK = 128; /** * <p> * 生成金鑰對(公鑰和私鑰) * </p> * * @return * @throws Exception */ public static Map<String, Object> genKeyPair() throws Exception { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); keyPairGen.initialize(1024); KeyPair keyPair = keyPairGen.generateKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); Map<String, Object> keyMap = new HashMap<String, Object>(2); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** * <p> * 用私鑰對資訊生成數字簽名 * </p> * * @param data 已加密資料 * @param privateKey 私鑰(BASE64編碼) * * @return * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(privateK); signature.update(data); return Base64Utils.encode(signature.sign()); } /** * <p> * 校驗數字簽名 * </p> * * @param data 已加密資料 * @param publicKey 公鑰(BASE64編碼) * @param sign 數字簽名 * * @return * @throws Exception * */ public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { byte[] keyBytes = Base64Utils.decode(publicKey); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PublicKey publicK = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(publicK); signature.update(data); return signature.verify(Base64Utils.decode(sign)); } /** * <P> * 私鑰解密 * </p> * * @param encryptedData 已加密資料 * @param privateKey 私鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對資料分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } /** * <p> * 公鑰解密 * </p> * * @param encryptedData 已加密資料 * @param publicKey 公鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception { byte[] keyBytes = Base64Utils.decode(publicKey); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對資料分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } /** * <p> * 公鑰加密 * </p> * * @param data 源資料 * @param publicKey 公鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception { byte[] keyBytes = Base64Utils.decode(publicKey); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); // 對資料加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對資料分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } /** * <p> * 私鑰加密 * </p> * * @param data 源資料 * @param privateKey 私鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對資料分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } /** * <p> * 獲取私鑰 * </p> * * @param keyMap 金鑰對 * @return * @throws Exception */ public static String getPrivateKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PRIVATE_KEY); return Base64Utils.encode(key.getEncoded()); } /** * <p> * 獲取公鑰 * </p> * * @param keyMap 金鑰對 * @return * @throws Exception */ public static String getPublicKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PUBLIC_KEY); return Base64Utils.encode(key.getEncoded()); } }
三、Hash演算法
何為Hash演算法?
Hash演算法是一種單向的加密演算法,即無法解密(依目前的計算力,還是可以使用暴力破解,MD5聽說被破解過)。
通常,Hash演算法有:MD2、MD4、MD5、HAVAL、SHA
import java.security.MessageDigest; import java.util.logging.Logger; /** * MD5加密演算法 */ public class MD5 { public static String MD5(String key) { char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; try { byte[] btInput = key.getBytes(); // 獲得MD5摘要演算法的 MessageDigest 物件 MessageDigest mdInst = MessageDigest.getInstance("MD5"); // 使用指定的位元組更新摘要 mdInst.update(btInput); // 獲得密文 byte[] md = mdInst.digest(); // 把密文轉換成十六進位制的字串形式 int j = md.length; char str[] = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; str[k++] = hexDigits[byte0 >>> 4 & 0xf]; str[k++] = hexDigits[byte0 & 0xf]; } return new String(str); } catch (Exception e) { return null; } } public static void main(String[] args){ String MD5_String; MD5_String = MD5("weiqingde"); System.out.println(MD5_String); } }
注:如果需要使用這些加密演算法,可以去下載apache 下的commons包,該包擁有很多對稱加密、非對稱加密、Hash加密實現工具