【前言】java
本文簡單的介紹了加密技術相關概念,最後總結了java中現有的加密技術以及使用方法和例子
【最簡單的加密】算法
1.簡單的概念apache
明文:加密前的信息數組
密文:機密後的信息app
算法:加密或解密的算法dom
密鑰:算法使用的鑰匙(讀做miyao,正確應該是miyue,可是你們都讀miyao)ide
2.簡單的例子函數
將123456每位數字都加1後獲得234567,工具
其中123456就是明文,234567就是密文,加密密鑰就是1,加密算法是每位加測試
3.對稱加密和非對稱加密
以上爲例,
123456-->234567的加密密鑰就是1,加密算法是每位+
234567-->123456的解密密鑰也是1,解密算法是每位-
其中加密算法(+)和解密算法(-)相對稱,這種加密算法就稱做對稱加密,
一樣,若是加密算法和解密算法不對稱就稱之爲非對稱加密。
4.算法舉例
衆多的加密手段大體能夠分爲單項加密和雙向加密。單項加密指經過對數據進行摘要計算生成密文,密文不可逆推還原,好比有Base6四、MD五、SHA等;雙向加密則相反,指能夠把密文逆推還原成明文,其中雙向加密又分爲對稱加密和非對稱加密。對稱加密是指數據使用者必須擁有一樣的密鑰才能夠進行加密解密,就像你們共同約定了一組暗號同樣,對稱加密的手段有DES、3DES、AES、IDEA、RC四、RC5等;而非對稱加密相對於對稱加密而言,無需擁有同一組密鑰,它是一種「信息公開的密鑰交換協議」。非對稱加密須要公開密鑰和私有密鑰兩組密鑰,公開密鑰和私有密鑰是配對起來的,也就是說使用公開密鑰進行數據加密,只有對應的私有密鑰才能進行解密。此類的加密手段有RSA、DSA等
對稱加密算法:DES算法,3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法,AES算法。
非對稱加密算法:RSA、Elgamal、揹包算法、Rabin、D-H、ECC。
經典的哈希算法:MD二、MD四、MD5 和 SHA-1(目的是將任意長輸入經過算法變爲固定長輸出,且保證輸入變化一點輸出都不一樣,且不能反向解密)
5.經典算法實現
5.1:AES算法
package com.meng.study.security; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; public class AESUtil { /** * AES加密 * * @param content * 待加密的內容 * @param encryptKey * 加密密鑰 * @return 加密後的byte[] * @throws Exception */ public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); random.setSeed(encryptKey.getBytes()); kgen.init(128, random); SecretKey secretKey = new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, secretKey); return cipher.doFinal(content.getBytes("UTF-8")); } /** * AES加密爲base 64 code * * @param content * 待加密的內容 * @param encryptKey * 加密密鑰 * @return 加密後的base 64 code * @throws Exception */ public static String aesEncrypt(String content, String encryptKey) throws Exception { return BASE64Util.base64Encode(aesEncryptToBytes(content, encryptKey)); } /** * AES解密 * * @param encryptBytes * 待解密的byte[] * @param decryptKey * 解密密鑰 * @return 解密後的String * @throws Exception */ public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); random.setSeed(decryptKey.getBytes()); kgen.init(128, random); SecretKey secretKey = new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, secretKey); byte[] decryptBytes = cipher.doFinal(encryptBytes); return new String(decryptBytes); } /** * 將base 64 code AES解密 * * @param encryptStr * 待解密的base 64 code * @param decryptKey * 解密密鑰 * @return 解密後的string * @throws Exception */ public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception { return aesDecryptByBytes(BASE64Util.base64Decode(encryptStr), decryptKey); } }
5.2:3DES算法
package com.meng.study.security; import java.io.UnsupportedEncodingException; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.apache.log4j.Logger; import com.meng.study.cache.GuavaCacheUtil; /** * * @author zhenbinmeng * */ public class DESUtil { private static Logger logger = Logger.getLogger(DESUtil.class); // 定義加密算法,DESede(即3DES) private static final String DESede = "DESede"; private static final String PASSWORD_CRYPT_KEY = "2015mengzhenbinStudyForSecurity@DESede"; /** * 加密方法 * * @param src * 源數據的字節數組 * @return */ public static byte[] encryptMode(byte[] src) { try { SecretKey deskey = new SecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede); // 生成密鑰 Cipher c1 = Cipher.getInstance(DESede); // 實例化負責加密/解密的Cipher工具類 c1.init(Cipher.ENCRYPT_MODE, deskey); // 初始化爲加密模式 return c1.doFinal(src); } catch (Exception e) { logger.error("DesUtil.encryptMode error", e); e.printStackTrace(); } return null; } /** * 加密方法(BASE64編碼返回) * * @param src * 源數據的字節數組 * @return */ public static String encryptModeBase64(byte[] src) { try { SecretKey deskey = new SecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede); // 生成密鑰 Cipher c1 = Cipher.getInstance(DESede); // 實例化負責加密/解密的Cipher工具類 c1.init(Cipher.ENCRYPT_MODE, deskey); // 初始化爲加密模式 return BASE64Util.base64Encode(c1.doFinal(src)); } catch (Exception e) { logger.error("DesUtil.encryptMode error", e); e.printStackTrace(); } return null; } /** * 解密函數 * * @param src * 密文的字節數組 * @return */ public static byte[] decryptMode(byte[] src) { try { SecretKey deskey = new SecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede); Cipher c1 = Cipher.getInstance(DESede); c1.init(Cipher.DECRYPT_MODE, deskey); // 初始化爲解密模式 return c1.doFinal(src); } catch (Exception e) { logger.error("DesUtil.decryptMode error", e); e.printStackTrace(); } return null; } /** * 解密函數(BASE64解碼後解密) * * @param src * 密文的字節數組 * @return */ public static String decryptModeBase64(String src) { try { SecretKey deskey = new SecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede); Cipher c1 = Cipher.getInstance(DESede); c1.init(Cipher.DECRYPT_MODE, deskey); // 初始化爲解密模式 return new String(c1.doFinal(BASE64Util.base64Decode(src))); } catch (Exception e) { logger.error("DesUtil.decryptMode error", e); e.printStackTrace(); } return null; } /* * 根據字符串生成密鑰字節數組 * * @param keyStr 密鑰字符串 * * @return * * @throws UnsupportedEncodingException */ public static byte[] build3DesKey(String keyStr) throws UnsupportedEncodingException { byte[] key = new byte[24]; // 聲明一個24位的字節數組,默認裏面都是0 byte[] temp = keyStr.getBytes("UTF-8"); // 將字符串轉成字節數組 /* * 執行數組拷貝 System.arraycopy(源數組,從源數組哪裏開始拷貝,目標數組,拷貝多少位) */ if (key.length > temp.length) { // 若是temp不夠24位,則拷貝temp數組整個長度的內容到key數組中 System.arraycopy(temp, 0, key, 0, temp.length); } else { // 若是temp大於24位,則拷貝temp數組24個長度的內容到key數組中 System.arraycopy(temp, 0, key, 0, key.length); } return key; } }
5.3:MD5算法
package com.meng.study.security; import java.security.MessageDigest; public class MD5Util { /** * 獲取byte[]的md5值 * * @param bytes * byte[] * @return md5 * @throws Exception */ public static byte[] md5(byte[] bytes) throws Exception { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(bytes); return md.digest(); } /** * 獲取字符串md5值 * * @param msg * @return md5 * @throws Exception */ public static byte[] md5(String msg) throws Exception { return md5(msg.getBytes()); } /** * 獲取字符串md5值 * * @param msg * @return md5 * @throws Exception */ public static String md5Hex(String msg) throws Exception { byte[] messageDigest = md5(msg.getBytes()); // Create Hex String StringBuffer hexString = new StringBuffer(); // 字節數組轉換爲 十六進制 數 for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } return hexString.toString(); } /** * 結合base64實現md5加密 * * @param msg * 待加密字符串 * @return 獲取md5後轉爲base64 * @throws Exception */ public static String md5Base64(String msg) throws Exception { return BASE64Util.base64Encode(md5(msg)); } }
5.4:SHA算法
package com.meng.study.security; import java.security.MessageDigest; public class SHAUtil { public static String SHA1(String decript) { try { MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1"); digest.update(decript.getBytes()); byte messageDigest[] = digest.digest(); // Create Hex String StringBuffer hexString = new StringBuffer(); // 字節數組轉換爲 十六進制 數 for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } return hexString.toString(); } catch (Exception e) { e.printStackTrace(); } return ""; } public static String SHA(String decript) { try { MessageDigest digest = java.security.MessageDigest.getInstance("SHA"); digest.update(decript.getBytes()); byte messageDigest[] = digest.digest(); // Create Hex String StringBuffer hexString = new StringBuffer(); // 字節數組轉換爲 十六進制 數 for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } return hexString.toString(); } catch (Exception e) { e.printStackTrace(); } return ""; } }
5.5:RSA算法
package com.meng.study.security; import java.math.BigInteger; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; import java.util.HashMap; import javax.crypto.Cipher; public class RSAUtil { /** * 生成公鑰和私鑰 * * @throws NoSuchAlgorithmException * */ public static HashMap<String, Object> getKeys() throws NoSuchAlgorithmException { HashMap<String, Object> map = new HashMap<String, Object>(); KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(1024); KeyPair keyPair = keyPairGen.generateKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); map.put("public", publicKey); map.put("private", privateKey); return map; } /** * 使用模和指數生成RSA公鑰 * 注意:【此代碼用了默認補位方式,爲RSA/None/PKCS1Padding,不一樣JDK默認的補位方式可能不一樣,如Android默認是RSA * /None/NoPadding】 * * @param modulus * 模 * @param exponent * 指數 * @return */ public static RSAPublicKey getPublicKey(String modulus, String exponent) { try { BigInteger b1 = new BigInteger(modulus); BigInteger b2 = new BigInteger(exponent); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2); return (RSAPublicKey) keyFactory.generatePublic(keySpec); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 使用模和指數生成RSA私鑰 * 注意:【此代碼用了默認補位方式,爲RSA/None/PKCS1Padding,不一樣JDK默認的補位方式可能不一樣,如Android默認是RSA * /None/NoPadding】 * * @param modulus * 模 * @param exponent * 指數 * @return */ public static RSAPrivateKey getPrivateKey(String modulus, String exponent) { try { BigInteger b1 = new BigInteger(modulus); BigInteger b2 = new BigInteger(exponent); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2); return (RSAPrivateKey) keyFactory.generatePrivate(keySpec); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 公鑰加密 * * @param data * @param publicKey * @return * @throws Exception */ public static String encryptByPublicKey(String data, RSAPublicKey publicKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); // 模長 int key_len = publicKey.getModulus().bitLength() / 8; // 加密數據長度 <= 模長-11 String[] datas = splitString(data, key_len - 11); String mi = ""; // 若是明文長度大於模長-11則要分組加密 for (String s : datas) { mi += bcd2Str(cipher.doFinal(s.getBytes())); } return mi; } /** * 私鑰解密 * * @param data * @param privateKey * @return * @throws Exception */ public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); // 模長 int key_len = privateKey.getModulus().bitLength() / 8; byte[] bytes = data.getBytes(); byte[] bcd = ASCII_To_BCD(bytes, bytes.length); // 若是密文長度大於模長則要分組解密 String ming = ""; byte[][] arrays = splitArray(bcd, key_len); for (byte[] arr : arrays) { ming += new String(cipher.doFinal(arr)); } return ming; } /** * ASCII碼轉BCD碼 * */ public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) { byte[] bcd = new byte[asc_len / 2]; int j = 0; for (int i = 0; i < (asc_len + 1) / 2; i++) { bcd[i] = asc_to_bcd(ascii[j++]); bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4)); } return bcd; } public static byte asc_to_bcd(byte asc) { byte bcd; if ((asc >= '0') && (asc <= '9')) bcd = (byte) (asc - '0'); else if ((asc >= 'A') && (asc <= 'F')) bcd = (byte) (asc - 'A' + 10); else if ((asc >= 'a') && (asc <= 'f')) bcd = (byte) (asc - 'a' + 10); else bcd = (byte) (asc - 48); return bcd; } /** * BCD轉字符串 */ public static String bcd2Str(byte[] bytes) { char temp[] = new char[bytes.length * 2], val; for (int i = 0; i < bytes.length; i++) { val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f); temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0'); val = (char) (bytes[i] & 0x0f); temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0'); } return new String(temp); } /** * 拆分字符串 */ public static String[] splitString(String string, int len) { int x = string.length() / len; int y = string.length() % len; int z = 0; if (y != 0) { z = 1; } String[] strings = new String[x + z]; String str = ""; for (int i = 0; i < x + z; i++) { if (i == x + z - 1 && y != 0) { str = string.substring(i * len, i * len + y); } else { str = string.substring(i * len, i * len + len); } strings[i] = str; } return strings; } /** * 拆分數組 */ public static byte[][] splitArray(byte[] data, int len) { int x = data.length / len; int y = data.length % len; int z = 0; if (y != 0) { z = 1; } byte[][] arrays = new byte[x + z][]; byte[] arr; for (int i = 0; i < x + z; i++) { arr = new byte[len]; if (i == x + z - 1 && y != 0) { System.arraycopy(data, i * len, arr, 0, y); } else { System.arraycopy(data, i * len, arr, 0, len); } arrays[i] = arr; } return arrays; } }
5.6:Base64算法
package com.meng.study.security; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; @SuppressWarnings("restriction") public class BASE64Util { /** * base 64 encode * * @param bytes * 待編碼的byte[] * @return 編碼後的base 64 code */ public static String base64Encode(byte[] bytes) { return new BASE64Encoder().encode(bytes); } /** * base 64 decode * * @param base64Code * 待解碼的base 64 code * @return 解碼後的byte[] * @throws Exception */ public static byte[] base64Decode(String base64Code) throws Exception { return new BASE64Decoder().decodeBuffer(base64Code); } }
5.7:測試代碼
package com.meng.study.security; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.util.HashMap; /** * 編碼工具類 1.將byte[]轉爲各類進制的字符串 2.base 64 encode 3.base 64 decode * * @author uikoo9 * @version 0.0.5.20140601 */ public class EncodeUtilTest { public static void main(String[] args) throws Exception { String msg = "我愛你"; System.out.println("轉換前:" + msg); //==Base64== String base64Str = BASE64Util.base64Encode(msg.getBytes()); System.out.println("Base64轉換後:" + base64Str); System.out.println("Base64解碼後:" + new String(BASE64Util.base64Decode(base64Str))); //==Md5== String md5Base64Str = MD5Util.md5Base64(msg); System.out.println("Md5後Base編碼轉換後:" + md5Base64Str); //==Des== byte[] des = DESUtil.encryptMode(msg.getBytes()); System.out.println("【DES加密後】:" + new String(des)); byte[] myMsgArr = DESUtil.decryptMode(des); System.out.println("【DES解密後】:" + new String(myMsgArr)); String desBase64Str = DESUtil.encryptModeBase64(msg.getBytes()); System.out.println("Des後Base64編碼轉換後:" + desBase64Str); System.out.println("Base64解碼後Des轉換後:" + new String(DESUtil.decryptModeBase64(desBase64Str))); //==Aes== String aesKey = "123456"; String aesEnStr= AESUtil.aesEncrypt(msg,aesKey); System.out.println("【AES加密Base64編碼後】:" +aesEnStr); String aesDeStr = AESUtil.aesDecrypt(aesEnStr,aesKey); System.out.println("【Base64解碼AES解密後】:" +aesDeStr); //==Rsa== HashMap<String, Object> keys = RSAUtil.getKeys(); RSAPublicKey publicKey = (RSAPublicKey) keys.get("public"); RSAPrivateKey privateKey = (RSAPrivateKey) keys.get("private"); RSAPublicKey pubKey = RSAUtil.getPublicKey(publicKey.getModulus().toString(), publicKey.getPublicExponent().toString()); RSAPrivateKey priKey = RSAUtil.getPrivateKey(privateKey.getModulus().toString(), privateKey.getPrivateExponent().toString()); String rsaEnStr = RSAUtil.encryptByPublicKey(msg, pubKey); System.out.println("【RSA公鑰加密後】:" +rsaEnStr); String rsaDeStr= RSAUtil.decryptByPrivateKey(rsaEnStr, priKey); System.out.println("【RSA私鑰解密後】:" +rsaDeStr); } }