面试必问:常用的加密算法有哪些?
加密算法我們整體可以分為:可逆加密和不可逆加密,可逆加密又可以分為:對稱加密和非對稱加密。
一、不可逆加密
常見的不可逆加密算法有MD5,HMAC,SHA1、SHA-224、SHA-256、SHA-384,和SHA-512,其中SHA-224、SHA-256、SHA-384,和SHA-512我們可以統(tǒng)稱為SHA2加密算法,SHA加密算法的安全性要比MD5更高,而SHA2加密算法比SHA1的要高。其中SHA后面的數(shù)字表示的是加密后的字符串長度,SHA1默認會產(chǎn)生一個160位的信息摘要。
不可逆加密算法最大的特點就是密鑰,但是HMAC是需要密鑰的【手動狗頭】。
由于這些加密都是不可逆的,因此比較常用的場景就是用戶密碼加密,其驗證過程就是通過比較兩個加密后的字符串是否一樣來確認身份的。網(wǎng)上也有很多自稱是可以破解MD5密碼的網(wǎng)站,其原理也是一樣,就是有一個巨大的資源庫,存放了許多字符串及對應(yīng)的MD5加密后的字符串,通過你輸入的MD5加密串來進行比較,如果過你的密碼復(fù)雜度比較低,還是有很大機率驗證出來的。
1.1 MD5
MD5信息摘要算法(英語:MD5 Message-Digest Algorithm),一種被廣泛使用的密碼散列函數(shù),可以產(chǎn)生出一個128位(16字節(jié))的散列值(hash value),用于確保信息傳輸完整一致。
MD5算法有以下特點:
1、壓縮性:無論數(shù)據(jù)長度是多少,計算出來的MD5值長度相同
2、容易計算性:由原數(shù)據(jù)容易計算出MD5值
3、抗修改性:即便修改一個字節(jié),計算出來的MD5值也會巨大差異
4、抗碰撞性:知道數(shù)據(jù)和MD5值,很小概率找到相同MD5值相同的原數(shù)據(jù)。
public?static?String?md5(String?text)?{MessageDigest?messageDigest?=?null;try?{messageDigest?=?MessageDigest.getInstance("MD5");}?catch?(NoSuchAlgorithmException?e)?{e.printStackTrace();}byte[]?bytes?=?messageDigest.digest(text.getBytes());return?Hex.encodeHexString(bytes);? }1.2 SHA系列
安全散列算法(英語:Secure Hash Algorithm,縮寫為SHA)是一個密碼散列函數(shù)家族,是FIPS所認證的安全散列算法。能計算出一個數(shù)字消息所對應(yīng)到的,長度固定的字符串(又稱消息摘要)的算法。且若輸入的消息不同,它們對應(yīng)到不同字符串的機率很高。
2005年8月17日的CRYPTO會議尾聲中王小云、姚期智、姚儲楓再度發(fā)表更有效率的SHA-1攻擊法,能在2的63次方個計算復(fù)雜度內(nèi)找到碰撞。
也就是說SHA-1加密算法有碰撞的可能性,雖然很小。
public?static?String?sha256(String?text)?{MessageDigest?messageDigest?=?null;try?{messageDigest?=?MessageDigest.getInstance("SHA-256");}?catch?(NoSuchAlgorithmException?e)?{e.printStackTrace();}byte[]?bytes?=?messageDigest.digest(text.getBytes());?return?Hex.encodeHexString(bytes);? }1.3 HMAC系列
HMAC是密鑰相關(guān)的哈希運算消息認證碼(Hash-based Message Authentication ?Code)的縮寫,由H.Krawezyk,M.Bellare,R.Canetti于1996年提出的一種基于Hash函數(shù)和密鑰進行消息認證的方法,并于1997年作為RFC2104被公布,并在IPSec和其他網(wǎng)絡(luò)協(xié)議(如SSL)中得以廣泛應(yīng)用,現(xiàn)在已經(jīng)成為事實上的Internet安全標準。它可以與任何迭代散列函數(shù)捆綁使用。
HMAC算法更像是一種加密算法,它引入了密鑰,其安全性已經(jīng)不完全依賴于所使用的Hash算法
public?static?String?hmacSha256(String?text,?SecretKeySpec?sk)?{Mac?mac?=?null;try?{mac?=?Mac.getInstance("HmacSHA256");}?catch?(NoSuchAlgorithmException?e)?{e.printStackTrace();}try?{mac.init(sk);}?catch?(InvalidKeyException?e)?{e.printStackTrace();}byte[]?rawHmac?=?mac.doFinal(text.getBytes());return?new?String(Base64.encodeBase64(rawHmac)); }如果要使用不可逆加密,推薦使用SHA256、SHA384、SHA512以及HMAC-SHA256、HMAC-SHA384、HMAC-SHA512這幾種算法。
二、對稱加密算法
對稱加密算法是應(yīng)用比較早的算法,在數(shù)據(jù)加密和解密的時用的都是同一個密鑰,這就造成了密鑰管理困難的問題。常見的對稱加密算法有DES、3DES、AES128、AES192、AES256(默認安裝的JDK尚不支持AES256,需要安裝對應(yīng)的jce補丁進行升級jce1.7,jce1.8)。其中AES后面的數(shù)字代表的是密鑰長度。對稱加密算法的安全性相對較低,比較適用的場景就是內(nèi)網(wǎng)環(huán)境中的加解密。
2.1 DES
DES是對稱加密算法領(lǐng)域中的典型算法,其密鑰默認長度為56位。
//?加密 public?static?String?encrypt(byte[]?dataSource,?String?password){try?{SecureRandom?random?=?new?SecureRandom();DESKeySpec?desKeySpec?=?new?DESKeySpec(password.getBytes());//創(chuàng)建一個密匙工廠,然后用它把DESKeySpec轉(zhuǎn)換成?SecretKeyFactory?secretKeyFactory?=?SecretKeyFactory.getInstance("DES");?SecretKey?secretKey?=?secretKeyFactory.generateSecret(desKeySpec);?//Cipher對象實際完成加密操作?Cipher?cipher?=?Cipher.getInstance("DES");?//用密匙初始化Cipher對象?cipher.init(Cipher.ENCRYPT_MODE,?secretKey,?random);?//正式執(zhí)行加密操作?return?Base64.encodeBase64String(cipher.doFinal(dataSource));?}?catch?(Throwable?e)?{?e.printStackTrace();?}?return?null;?}? //?解密 public?static?String?decrypt(String?src,?String?password)?throws?Exception{?//?DES算法要求有一個可信任的隨機數(shù)源?SecureRandom?random?=?new?SecureRandom();?//?創(chuàng)建一個DESKeySpec對象?DESKeySpec?desKeySpec?=?new?DESKeySpec(password.getBytes());?//?創(chuàng)建一個密匙工廠?SecretKeyFactory?keyFactory?=?SecretKeyFactory.getInstance("DES");?//?將DESKeySpec對象轉(zhuǎn)換成SecretKey對象?SecretKey?secretKey?=?keyFactory.generateSecret(desKeySpec);?//?Cipher對象實際完成解密操作?Cipher?cipher?=?Cipher.getInstance("DES");?//?用密匙初始化Cipher對象?cipher.init(Cipher.DECRYPT_MODE,?secretKey,?random);?//?真正開始解密操作?return?new?String(cipher.doFinal(Base64.decodeBase64(src)));? }2.2 3DES
3DES(即Triple DES)是DES向AES過渡的加密算法,它使用3條56位的密鑰對數(shù)據(jù)進行三次加密。是DES的一個更安全的變形。它以DES為基本模塊,通過組合分組方法設(shè)計出分組加密算法。比起最初的DES,3DES更為安全。密鑰長度默認為168位,還可以選擇128位。
public?static?String?encryptThreeDESECB(String?src,?String?key)?{try{DESedeKeySpec?dks?=?new?DESedeKeySpec(key.getBytes("UTF-8"));SecretKeyFactory?keyFactory?=?SecretKeyFactory.getInstance("DESede");SecretKey?securekey?=?keyFactory.generateSecret(dks);Cipher?cipher?=?Cipher.getInstance("DESede/ECB/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE,?securekey);byte[]?b?=?cipher.doFinal(src.getBytes("UTF-8"));String?ss?=?new?String(Base64.encodeBase64(b));ss?=?ss.replaceAll("\\+",?"-");ss?=?ss.replaceAll("/",?"_");return?ss;}?catch(Exception?ex){ex.printStackTrace();return?src;} }public?static?String?decryptThreeDESECB(String?src,?String?key)?{try{src?=?src.replaceAll("-",?"+");src?=?src.replaceAll("_",?"/");byte[]?bytesrc?=?Base64.decodeBase64(src.getBytes("UTF-8"));//?--解密的keyDESedeKeySpec?dks?=?new?DESedeKeySpec(key.getBytes("UTF-8"));SecretKeyFactory?keyFactory?=?SecretKeyFactory.getInstance("DESede");SecretKey?securekey?=?keyFactory.generateSecret(dks);//?--Chipher對象解密Cipher?cipher?=?Cipher.getInstance("DESede/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE,?securekey);byte[]?retByte?=?cipher.doFinal(bytesrc);return?new?String(retByte,?"UTF-8");}?catch(Exception?ex){ex.printStackTrace();return?src;} }2.3 AES
AES高級數(shù)據(jù)加密標準,能夠有效抵御已知的針對DES算法的所有攻擊,默認密鑰長度為128位,還可以供選擇192位,256位。這里順便提一句這個位指的是bit。
private?static?final?String?defaultCharset?=?"UTF-8"; private?static?final?String?KEY_AES?=?"AES"; private?static?final?String?KEY_MD5?=?"MD5"; private?static?MessageDigest?md5Digest; static?{try?{md5Digest?=?MessageDigest.getInstance(KEY_MD5);}?catch?(NoSuchAlgorithmException?e)?{} } /***?加密*/ public?static?String?encrypt(String?data,?String?key)?{return?doAES(data,?key,?Cipher.ENCRYPT_MODE); } /***?解密*/ public?static?String?decrypt(String?data,?String?key)?{return?doAES(data,?key,?Cipher.DECRYPT_MODE); }/***?加解密*/ private?static?String?doAES(String?data,?String?key,?int?mode)?{try?{boolean?encrypt?=?mode?==?Cipher.ENCRYPT_MODE;byte[]?content;if?(encrypt)?{content?=?data.getBytes(defaultCharset);}?else?{content?=?Base64.decodeBase64(data.getBytes());}SecretKeySpec?keySpec?=?new?SecretKeySpec(md5Digest.digest(key.getBytes(defaultCharset)),?KEY_AES);Cipher?cipher?=?Cipher.getInstance(KEY_AES);//?創(chuàng)建密碼器cipher.init(mode,?keySpec);//?初始化byte[]?result?=?cipher.doFinal(content);if?(encrypt)?{return?new?String(Base64.encodeBase64(result));}?else?{return?new?String(result,?defaultCharset);}}?catch?(Exception?e)?{}return?null; }推薦使用對稱加密算法有:AES128、AES192、AES256。
三、非對稱加密算法
非對稱加密算法有兩個密鑰,這兩個密鑰完全不同但又完全匹配。只有使用匹配的一對公鑰和私鑰,才能完成對明文的加密和解密過程。常見的非對稱加密有RSA、SM2等。
3.1 RSA
RSA密鑰至少為500位長,一般推薦使用1024位。
//非對稱密鑰算法 public?static?final?String?KEY_ALGORITHM?=?"RSA";/***?密鑰長度,DH算法的默認密鑰長度是1024*?密鑰長度必須是64的倍數(shù),在512到65536位之間*/ private?static?final?int?KEY_SIZE?=?1024; //公鑰 private?static?final?String?PUBLIC_KEY?=?"RSAPublicKey"; //私鑰 private?static?final?String?PRIVATE_KEY?=?"RSAPrivateKey"; /***?初始化密鑰對**?@return?Map?甲方密鑰的Map*/ public?static?Map<String,?Object>?initKey()?throws?Exception?{//實例化密鑰生成器KeyPairGenerator?keyPairGenerator?=?KeyPairGenerator.getInstance(KEY_ALGORITHM);//初始化密鑰生成器keyPairGenerator.initialize(KEY_SIZE);//生成密鑰對KeyPair?keyPair?=?keyPairGenerator.generateKeyPair();//甲方公鑰RSAPublicKey?publicKey?=?(RSAPublicKey)?keyPair.getPublic();//甲方私鑰RSAPrivateKey?privateKey?=?(RSAPrivateKey)?keyPair.getPrivate();//將密鑰存儲在map中Map<String,?Object>?keyMap?=?new?HashMap<String,?Object>();keyMap.put(PUBLIC_KEY,?publicKey);keyMap.put(PRIVATE_KEY,?privateKey);return?keyMap; } /***?私鑰加密**?@param?data?待加密數(shù)據(jù)*?@param?key??密鑰*?@return?byte[]?加密數(shù)據(jù)*/ public?static?byte[]?encryptByPrivateKey(byte[]?data,?byte[]?key)?throws?Exception?{//取得私鑰PKCS8EncodedKeySpec?pkcs8KeySpec?=?new?PKCS8EncodedKeySpec(key);KeyFactory?keyFactory?=?KeyFactory.getInstance(KEY_ALGORITHM);//生成私鑰PrivateKey?privateKey?=?keyFactory.generatePrivate(pkcs8KeySpec);//數(shù)據(jù)加密Cipher?cipher?=?Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE,?privateKey);return?cipher.doFinal(data); }/***?公鑰加密**?@param?data?待加密數(shù)據(jù)*?@param?key??密鑰*?@return?byte[]?加密數(shù)據(jù)*/ public?static?byte[]?encryptByPublicKey(byte[]?data,?byte[]?key)?throws?Exception?{//實例化密鑰工廠KeyFactory?keyFactory?=?KeyFactory.getInstance(KEY_ALGORITHM);//初始化公鑰//密鑰材料轉(zhuǎn)換X509EncodedKeySpec?x509KeySpec?=?new?X509EncodedKeySpec(key);//產(chǎn)生公鑰PublicKey?pubKey?=?keyFactory.generatePublic(x509KeySpec);//數(shù)據(jù)加密Cipher?cipher?=?Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE,?pubKey);return?cipher.doFinal(data); }/***?私鑰解密**?@param?data?待解密數(shù)據(jù)*?@param?key??密鑰*?@return?byte[]?解密數(shù)據(jù)*/ public?static?byte[]?decryptByPrivateKey(byte[]?data,?byte[]?key)?throws?Exception?{//取得私鑰PKCS8EncodedKeySpec?pkcs8KeySpec?=?new?PKCS8EncodedKeySpec(key);KeyFactory?keyFactory?=?KeyFactory.getInstance(KEY_ALGORITHM);//生成私鑰PrivateKey?privateKey?=?keyFactory.generatePrivate(pkcs8KeySpec);//數(shù)據(jù)解密Cipher?cipher?=?Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE,?privateKey);return?cipher.doFinal(data); }/***?公鑰解密**?@param?data?待解密數(shù)據(jù)*?@param?key??密鑰*?@return?byte[]?解密數(shù)據(jù)*/ public?static?byte[]?decryptByPublicKey(byte[]?data,?byte[]?key)?throws?Exception?{//實例化密鑰工廠KeyFactory?keyFactory?=?KeyFactory.getInstance(KEY_ALGORITHM);//初始化公鑰//密鑰材料轉(zhuǎn)換X509EncodedKeySpec?x509KeySpec?=?new?X509EncodedKeySpec(key);//產(chǎn)生公鑰PublicKey?pubKey?=?keyFactory.generatePublic(x509KeySpec);//數(shù)據(jù)解密Cipher?cipher?=?Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE,?pubKey);return?cipher.doFinal(data); }/***?取得私鑰**?@param?keyMap?密鑰map*?@return?byte[]?私鑰*/ public?static?byte[]?getPrivateKey(Map<String,?Object>?keyMap)?{Key?key?=?(Key)?keyMap.get(PRIVATE_KEY);return?key.getEncoded(); }/***?取得公鑰**?@param?keyMap?密鑰map*?@return?byte[]?公鑰*/ public?static?byte[]?getPublicKey(Map<String,?Object>?keyMap)?throws?Exception?{Key?key?=?(Key)?keyMap.get(PUBLIC_KEY);return?key.getEncoded(); }四、加密鹽
加密鹽也是比較常聽到的一個概念,鹽就是一個隨機字符串用來和我們的加密串拼接后進行加密。加鹽主要是為了提供加密字符串的安全性。假如有一個加鹽后的加密串,黑客通過一定手段這個加密串,他拿到的明文,并不是我們加密前的字符串,而是加密前的字符串和鹽組合的字符串,這樣相對來說又增加了字符串的安全性。
文中的一些算法來源于網(wǎng)絡(luò),可直接復(fù)制使用。
比較推薦的幾個加密算法有:
-
不可逆加密:SHA256、SHA384、SHA512以及HMAC-SHA256、HMAC-SHA384、HMAC-SHA512
-
對稱加密算法:AES、3DES
-
非對稱加密算法:RSA
總結(jié)
以上是生活随笔為你收集整理的面试必问:常用的加密算法有哪些?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 支付宝二面:Mybatis 接口 Map
- 下一篇: Docker 极简入门教程,傻瓜都能看懂