<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官:說(shuō)一下你常用的加密算法

          共 11898字,需瀏覽 24分鐘

           ·

          2020-08-03 23:44

          加密算法我們整體可以分為:可逆加密和不可逆加密,可逆加密又可以分為:對(duì)稱(chēng)加密和非對(duì)稱(chēng)加密。

          一、不可逆加密

          常見(jiàn)的不可逆加密算法有MD5HMACSHA1SHA-224SHA-256SHA-384,和SHA-512,其中SHA-224SHA-256SHA-384,和SHA-512我們可以統(tǒng)稱(chēng)為SHA2加密算法,SHA加密算法的安全性要比MD5更高,而SHA2加密算法比SHA1的要高。其中SHA后面的數(shù)字表示的是加密后的字符串長(zhǎng)度,SHA1默認(rèn)會(huì)產(chǎn)生一個(gè)160位的信息摘要。

          不可逆加密算法最大的特點(diǎn)就是密鑰,但是HMAC是需要密鑰的【手動(dòng)狗頭】。

          由于這些加密都是不可逆的,因此比較常用的場(chǎng)景就是用戶(hù)密碼加密,其驗(yàn)證過(guò)程就是通過(guò)比較兩個(gè)加密后的字符串是否一樣來(lái)確認(rèn)身份的。網(wǎng)上也有很多自稱(chēng)是可以破解MD5密碼的網(wǎng)站,其原理也是一樣,就是有一個(gè)巨大的資源庫(kù),存放了許多字符串及對(duì)應(yīng)的MD5加密后的字符串,通過(guò)你輸入的MD5加密串來(lái)進(jìn)行比較,如果過(guò)你的密碼復(fù)雜度比較低,還是有很大機(jī)率驗(yàn)證出來(lái)的。

          1.1 MD5

          MD5信息摘要算法(英語(yǔ):MD5 Message-Digest Algorithm),一種被廣泛使用的密碼散列函數(shù),可以產(chǎn)生出一個(gè)128位(16字節(jié))的散列值(hash value),用于確保信息傳輸完整一致。

          MD5算法有以下特點(diǎn):

          1、壓縮性:無(wú)論數(shù)據(jù)長(zhǎng)度是多少,計(jì)算出來(lái)的MD5值長(zhǎng)度相同

          2、容易計(jì)算性:由原數(shù)據(jù)容易計(jì)算出MD5

          3、抗修改性:即便修改一個(gè)字節(jié),計(jì)算出來(lái)的MD5值也會(huì)巨大差異

          4、抗碰撞性:知道數(shù)據(jù)和MD5值,很小概率找到相同MD5值相同的原數(shù)據(jù)。

           1public?static?String?md5(String?text)?{
          2????MessageDigest?messageDigest?=?null;
          3????try?{
          4????????messageDigest?=?MessageDigest.getInstance("MD5");
          5????}?catch?(NoSuchAlgorithmException?e)?{
          6????????e.printStackTrace();
          7????}
          8????byte[]?bytes?=?messageDigest.digest(text.getBytes());
          9????return?Hex.encodeHexString(bytes);?
          10}

          1.2 SHA系列

          安全散列算法(英語(yǔ):Secure Hash Algorithm,縮寫(xiě)為SHA)是一個(gè)密碼散列函數(shù)家族,是FIPS所認(rèn)證的安全散列算法。能計(jì)算出一個(gè)數(shù)字消息所對(duì)應(yīng)到的,長(zhǎng)度固定的字符串(又稱(chēng)消息摘要)的算法。且若輸入的消息不同,它們對(duì)應(yīng)到不同字符串的機(jī)率很高。

          2005年8月17日的CRYPTO會(huì)議尾聲中王小云、姚期智、姚儲(chǔ)楓再度發(fā)表更有效率的SHA-1攻擊法,能在2的63次方個(gè)計(jì)算復(fù)雜度內(nèi)找到碰撞。

          也就是說(shuō)SHA-1加密算法有碰撞的可能性,雖然很小。

           1public?static?String?sha256(String?text)?{
          2????MessageDigest?messageDigest?=?null;
          3????try?{
          4????????messageDigest?=?MessageDigest.getInstance("SHA-256");
          5????}?catch?(NoSuchAlgorithmException?e)?{
          6????????e.printStackTrace();
          7????}
          8????byte[]?bytes?=?messageDigest.digest(text.getBytes());?
          9????return?Hex.encodeHexString(bytes);?
          10}

          1.3 HMAC系列

          HMAC是密鑰相關(guān)的哈希運(yùn)算消息認(rèn)證碼(Hash-based Message Authentication ?Code)的縮寫(xiě),由H.Krawezyk,M.Bellare,R.Canetti于1996年提出的一種基于Hash函數(shù)和密鑰進(jìn)行消息認(rèn)證的方法,并于1997年作為RFC2104被公布,并在IPSec和其他網(wǎng)絡(luò)協(xié)議(如SSL)中得以廣泛應(yīng)用,現(xiàn)在已經(jīng)成為事實(shí)上的Internet安全標(biāo)準(zhǔn)。它可以與任何迭代散列函數(shù)捆綁使用。

          HMAC算法更像是一種加密算法,它引入了密鑰,其安全性已經(jīng)不完全依賴(lài)于所使用的Hash算法

           1public?static?String?hmacSha256(String?text,?SecretKeySpec?sk)?{
          2????Mac?mac?=?null;
          3????try?{
          4????????mac?=?Mac.getInstance("HmacSHA256");
          5????}?catch?(NoSuchAlgorithmException?e)?{
          6????????e.printStackTrace();
          7????}
          8????try?{
          9????????mac.init(sk);
          10????}?catch?(InvalidKeyException?e)?{
          11????????e.printStackTrace();
          12????}
          13????byte[]?rawHmac?=?mac.doFinal(text.getBytes());
          14????return?new?String(Base64.encodeBase64(rawHmac));
          15}

          如果要使用不可逆加密,推薦使用SHA256、SHA384、SHA512以及HMAC-SHA256、HMAC-SHA384、HMAC-SHA512這幾種算法。

          二、對(duì)稱(chēng)加密算法

          對(duì)稱(chēng)加密算法是應(yīng)用比較早的算法,在數(shù)據(jù)加密和解密的時(shí)用的都是同一個(gè)密鑰,這就造成了密鑰管理困難的問(wèn)題。常見(jiàn)的對(duì)稱(chēng)加密算法有DES3DESAES128AES192AES256 (默認(rèn)安裝的 JDK 尚不支持 AES256,需要安裝對(duì)應(yīng)的 jce 補(bǔ)丁進(jìn)行升級(jí) jce1.7jce1.8)。其中AES后面的數(shù)字代表的是密鑰長(zhǎng)度。對(duì)稱(chēng)加密算法的安全性相對(duì)較低,比較適用的場(chǎng)景就是內(nèi)網(wǎng)環(huán)境中的加解密。

          2.1 DES

          DES是對(duì)稱(chēng)加密算法領(lǐng)域中的典型算法,其密鑰默認(rèn)長(zhǎng)度為56位。

           1//?加密
          2public?static?String?encrypt(byte[]?dataSource,?String?password){
          3?????try?{
          4?????????SecureRandom?random?=?new?SecureRandom();
          5?????????DESKeySpec?desKeySpec?=?new?DESKeySpec(password.getBytes());
          6?????????//創(chuàng)建一個(gè)密匙工廠,然后用它把DESKeySpec轉(zhuǎn)換成?
          7?????????SecretKeyFactory?secretKeyFactory?=?SecretKeyFactory.getInstance("DES");?
          8?????????SecretKey?secretKey?=?secretKeyFactory.generateSecret(desKeySpec);?
          9?????????//Cipher對(duì)象實(shí)際完成加密操作?
          10?????????Cipher?cipher?=?Cipher.getInstance("DES");?
          11?????????//用密匙初始化Cipher對(duì)象?
          12?????????cipher.init(Cipher.ENCRYPT_MODE,?secretKey,?random);?
          13?????????//正式執(zhí)行加密操作?
          14?????????return?Base64.encodeBase64String(cipher.doFinal(dataSource));?
          15?????}?catch?(Throwable?e)?{?
          16?????????e.printStackTrace();?
          17?????}?return?null;?
          18?}?
          19//?解密
          20public?static?String?decrypt(String?src,?String?password)?throws?Exception{?
          21????//?DES算法要求有一個(gè)可信任的隨機(jī)數(shù)源?
          22????SecureRandom?random?=?new?SecureRandom();?
          23????//?創(chuàng)建一個(gè)DESKeySpec對(duì)象?
          24????DESKeySpec?desKeySpec?=?new?DESKeySpec(password.getBytes());?
          25????//?創(chuàng)建一個(gè)密匙工廠?
          26????SecretKeyFactory?keyFactory?=?SecretKeyFactory.getInstance("DES");?
          27????//?將DESKeySpec對(duì)象轉(zhuǎn)換成SecretKey對(duì)象?
          28????SecretKey?secretKey?=?keyFactory.generateSecret(desKeySpec);?
          29????//?Cipher對(duì)象實(shí)際完成解密操作?
          30????Cipher?cipher?=?Cipher.getInstance("DES");?
          31????//?用密匙初始化Cipher對(duì)象?
          32????cipher.init(Cipher.DECRYPT_MODE,?secretKey,?random);?
          33????//?真正開(kāi)始解密操作?
          34????return?new?String(cipher.doFinal(Base64.decodeBase64(src)));?
          35}

          2.2 3DES

          3DES(即Triple DES)是DESAES過(guò)渡的加密算法,它使用3條56位的密鑰對(duì)數(shù)據(jù)進(jìn)行三次加密。是DES的一個(gè)更安全的變形。它以DES為基本模塊,通過(guò)組合分組方法設(shè)計(jì)出分組加密算法。比起最初的DES3DES更為安全。密鑰長(zhǎng)度默認(rèn)為168位,還可以選擇128位。

           1public?static?String?encryptThreeDESECB(String?src,?String?key)?{
          2????try{
          3????????DESedeKeySpec?dks?=?new?DESedeKeySpec(key.getBytes("UTF-8"));
          4????????SecretKeyFactory?keyFactory?=?SecretKeyFactory.getInstance("DESede");
          5????????SecretKey?securekey?=?keyFactory.generateSecret(dks);
          6
          7????????Cipher?cipher?=?Cipher.getInstance("DESede/ECB/PKCS5Padding");
          8????????cipher.init(Cipher.ENCRYPT_MODE,?securekey);
          9????????byte[]?b?=?cipher.doFinal(src.getBytes("UTF-8"));
          10
          11????????String?ss?=?new?String(Base64.encodeBase64(b));
          12????????ss?=?ss.replaceAll("\\+",?"-");
          13????????ss?=?ss.replaceAll("/",?"_");
          14????????return?ss;
          15????}?catch(Exception?ex){
          16????????ex.printStackTrace();
          17????????return?src;
          18????}
          19}
          20
          21public?static?String?decryptThreeDESECB(String?src,?String?key)?{
          22????try{
          23????????src?=?src.replaceAll("-",?"+");
          24????????src?=?src.replaceAll("_",?"/");
          25????????byte[]?bytesrc?=?Base64.decodeBase64(src.getBytes("UTF-8"));
          26????????//?--解密的key
          27????????DESedeKeySpec?dks?=?new?DESedeKeySpec(key.getBytes("UTF-8"));
          28????????SecretKeyFactory?keyFactory?=?SecretKeyFactory.getInstance("DESede");
          29????????SecretKey?securekey?=?keyFactory.generateSecret(dks);
          30
          31????????//?--Chipher對(duì)象解密
          32????????Cipher?cipher?=?Cipher.getInstance("DESede/ECB/PKCS5Padding");
          33????????cipher.init(Cipher.DECRYPT_MODE,?securekey);
          34????????byte[]?retByte?=?cipher.doFinal(bytesrc);
          35
          36????????return?new?String(retByte,?"UTF-8");
          37????}?catch(Exception?ex){
          38????????ex.printStackTrace();
          39????????return?src;
          40????}
          41}

          2.3 AES

          AES 高級(jí)數(shù)據(jù)加密標(biāo)準(zhǔn),能夠有效抵御已知的針對(duì)DES算法的所有攻擊,默認(rèn)密鑰長(zhǎng)度為128位,還可以供選擇192位,256位。這里順便提一句這個(gè)位指的是bit。

           1private?static?final?String?defaultCharset?=?"UTF-8";
          2private?static?final?String?KEY_AES?=?"AES";
          3private?static?final?String?KEY_MD5?=?"MD5";
          4private?static?MessageDigest?md5Digest;
          5static?{
          6????try?{
          7????????md5Digest?=?MessageDigest.getInstance(KEY_MD5);
          8????}?catch?(NoSuchAlgorithmException?e)?{
          9
          10????}
          11}
          12/**
          13??*?加密
          14??*/

          15public?static?String?encrypt(String?data,?String?key)?{
          16????return?doAES(data,?key,?Cipher.ENCRYPT_MODE);
          17}
          18/**
          19??*?解密
          20??*/

          21public?static?String?decrypt(String?data,?String?key)?{
          22????return?doAES(data,?key,?Cipher.DECRYPT_MODE);
          23}
          24
          25
          26/**
          27??*?加解密
          28??*/

          29private?static?String?doAES(String?data,?String?key,?int?mode)?{
          30????try?{
          31????????boolean?encrypt?=?mode?==?Cipher.ENCRYPT_MODE;
          32????????byte[]?content;
          33????????if?(encrypt)?{
          34????????????content?=?data.getBytes(defaultCharset);
          35????????}?else?{
          36????????????content?=?Base64.decodeBase64(data.getBytes());
          37????????}
          38????????SecretKeySpec?keySpec?=?new?SecretKeySpec(md5Digest.digest(key.getBytes(defaultCharset))
          39??????????????????????????????????????????????????,?KEY_AES);
          40????????Cipher?cipher?=?Cipher.getInstance(KEY_AES);//?創(chuàng)建密碼器
          41????????cipher.init(mode,?keySpec);//?初始化
          42????????byte[]?result?=?cipher.doFinal(content);
          43????????if?(encrypt)?{
          44????????????return?new?String(Base64.encodeBase64(result));
          45????????}?else?{
          46????????????return?new?String(result,?defaultCharset);
          47????????}
          48????}?catch?(Exception?e)?{
          49????}
          50????return?null;
          51}

          推薦使用對(duì)稱(chēng)加密算法有:AES128AES192AES256

          三、非對(duì)稱(chēng)加密算法

          非對(duì)稱(chēng)加密算法有兩個(gè)密鑰,這兩個(gè)密鑰完全不同但又完全匹配。只有使用匹配的一對(duì)公鑰和私鑰,才能完成對(duì)明文的加密和解密過(guò)程。常見(jiàn)的非對(duì)稱(chēng)加密有RSASM2等。

          3.1 RSA

          RSA密鑰至少為500位長(zhǎng),一般推薦使用1024位。

            1//非對(duì)稱(chēng)密鑰算法
          2public?static?final?String?KEY_ALGORITHM?=?"RSA";
          3
          4/**
          5??*?密鑰長(zhǎng)度,DH算法的默認(rèn)密鑰長(zhǎng)度是1024
          6??*?密鑰長(zhǎng)度必須是64的倍數(shù),在512到65536位之間
          7??*/

          8private?static?final?int?KEY_SIZE?=?1024;
          9//公鑰
          10private?static?final?String?PUBLIC_KEY?=?"RSAPublicKey";
          11//私鑰
          12private?static?final?String?PRIVATE_KEY?=?"RSAPrivateKey";
          13/**
          14??*?初始化密鑰對(duì)
          15??*
          16??*?@return?Map?甲方密鑰的Map
          17??*/

          18public?static?Map?initKey()?throws?Exception?{
          19????//實(shí)例化密鑰生成器
          20????KeyPairGenerator?keyPairGenerator?=?KeyPairGenerator.getInstance(KEY_ALGORITHM);
          21????//初始化密鑰生成器
          22????keyPairGenerator.initialize(KEY_SIZE);
          23????//生成密鑰對(duì)
          24????KeyPair?keyPair?=?keyPairGenerator.generateKeyPair();
          25????//甲方公鑰
          26????RSAPublicKey?publicKey?=?(RSAPublicKey)?keyPair.getPublic();
          27????//甲方私鑰
          28????RSAPrivateKey?privateKey?=?(RSAPrivateKey)?keyPair.getPrivate();
          29????//將密鑰存儲(chǔ)在map中
          30????Map?keyMap?=?new?HashMap();
          31????keyMap.put(PUBLIC_KEY,?publicKey);
          32????keyMap.put(PRIVATE_KEY,?privateKey);
          33????return?keyMap;
          34}
          35/**
          36??*?私鑰加密
          37??*
          38??*?@param?data?待加密數(shù)據(jù)
          39??*?@param?key??密鑰
          40??*?@return?byte[]?加密數(shù)據(jù)
          41??*/

          42public?static?byte[]?encryptByPrivateKey(byte[]?data,?byte[]?key)?throws?Exception?{
          43
          44????//取得私鑰
          45????PKCS8EncodedKeySpec?pkcs8KeySpec?=?new?PKCS8EncodedKeySpec(key);
          46????KeyFactory?keyFactory?=?KeyFactory.getInstance(KEY_ALGORITHM);
          47????//生成私鑰
          48????PrivateKey?privateKey?=?keyFactory.generatePrivate(pkcs8KeySpec);
          49????//數(shù)據(jù)加密
          50????Cipher?cipher?=?Cipher.getInstance(keyFactory.getAlgorithm());
          51????cipher.init(Cipher.ENCRYPT_MODE,?privateKey);
          52????return?cipher.doFinal(data);
          53}
          54
          55/**
          56??*?公鑰加密
          57??*
          58??*?@param?data?待加密數(shù)據(jù)
          59??*?@param?key??密鑰
          60??*?@return?byte[]?加密數(shù)據(jù)
          61??*/

          62public?static?byte[]?encryptByPublicKey(byte[]?data,?byte[]?key)?throws?Exception?{
          63
          64????//實(shí)例化密鑰工廠
          65????KeyFactory?keyFactory?=?KeyFactory.getInstance(KEY_ALGORITHM);
          66????//初始化公鑰
          67????//密鑰材料轉(zhuǎn)換
          68????X509EncodedKeySpec?x509KeySpec?=?new?X509EncodedKeySpec(key);
          69????//產(chǎn)生公鑰
          70????PublicKey?pubKey?=?keyFactory.generatePublic(x509KeySpec);
          71????//數(shù)據(jù)加密
          72????Cipher?cipher?=?Cipher.getInstance(keyFactory.getAlgorithm());
          73????cipher.init(Cipher.ENCRYPT_MODE,?pubKey);
          74????return?cipher.doFinal(data);
          75}
          76
          77/**
          78??*?私鑰解密
          79??*
          80??*?@param?data?待解密數(shù)據(jù)
          81??*?@param?key??密鑰
          82??*?@return?byte[]?解密數(shù)據(jù)
          83??*/

          84public?static?byte[]?decryptByPrivateKey(byte[]?data,?byte[]?key)?throws?Exception?{
          85????//取得私鑰
          86????PKCS8EncodedKeySpec?pkcs8KeySpec?=?new?PKCS8EncodedKeySpec(key);
          87????KeyFactory?keyFactory?=?KeyFactory.getInstance(KEY_ALGORITHM);
          88????//生成私鑰
          89????PrivateKey?privateKey?=?keyFactory.generatePrivate(pkcs8KeySpec);
          90????//數(shù)據(jù)解密
          91????Cipher?cipher?=?Cipher.getInstance(keyFactory.getAlgorithm());
          92????cipher.init(Cipher.DECRYPT_MODE,?privateKey);
          93????return?cipher.doFinal(data);
          94}
          95
          96/**
          97??*?公鑰解密
          98??*
          99??*?@param?data?待解密數(shù)據(jù)
          100??*?@param?key??密鑰
          101??*?@return?byte[]?解密數(shù)據(jù)
          102??*/

          103public?static?byte[]?decryptByPublicKey(byte[]?data,?byte[]?key)?throws?Exception?{
          104
          105????//實(shí)例化密鑰工廠
          106????KeyFactory?keyFactory?=?KeyFactory.getInstance(KEY_ALGORITHM);
          107????//初始化公鑰
          108????//密鑰材料轉(zhuǎn)換
          109????X509EncodedKeySpec?x509KeySpec?=?new?X509EncodedKeySpec(key);
          110????//產(chǎn)生公鑰
          111????PublicKey?pubKey?=?keyFactory.generatePublic(x509KeySpec);
          112????//數(shù)據(jù)解密
          113????Cipher?cipher?=?Cipher.getInstance(keyFactory.getAlgorithm());
          114????cipher.init(Cipher.DECRYPT_MODE,?pubKey);
          115????return?cipher.doFinal(data);
          116}
          117
          118/**
          119??*?取得私鑰
          120??*
          121??*?@param?keyMap?密鑰map
          122??*?@return?byte[]?私鑰
          123??*/

          124public?static?byte[]?getPrivateKey(Map?keyMap)?{
          125????Key?key?=?(Key)?keyMap.get(PRIVATE_KEY);
          126????return?key.getEncoded();
          127}
          128
          129/**
          130??*?取得公鑰
          131??*
          132??*?@param?keyMap?密鑰map
          133??*?@return?byte[]?公鑰
          134??*/

          135public?static?byte[]?getPublicKey(Map?keyMap)?throws?Exception?{
          136????Key?key?=?(Key)?keyMap.get(PUBLIC_KEY);
          137????return?key.getEncoded();
          138}

          四、加密鹽

          加密鹽也是比較常聽(tīng)到的一個(gè)概念,鹽就是一個(gè)隨機(jī)字符串用來(lái)和我們的加密串拼接后進(jìn)行加密。加鹽主要是為了提供加密字符串的安全性。假如有一個(gè)加鹽后的加密串,黑客通過(guò)一定手段這個(gè)加密串,他拿到的明文,并不是我們加密前的字符串,而是加密前的字符串和鹽組合的字符串,這樣相對(duì)來(lái)說(shuō)又增加了字符串的安全性。

          文中的一些算法來(lái)源于網(wǎng)絡(luò),可直接復(fù)制使用

          比較推薦的幾個(gè)加密算法有:

          • 不可逆加密:SHA256SHA384SHA512以及HMAC-SHA256HMAC-SHA384HMAC-SHA512

          • 對(duì)稱(chēng)加密算法:AES3DES

          • 非對(duì)稱(chēng)加密算法:RSA


          < END >


          往期精選
          ??Nginx超簡(jiǎn)單教程
          ??服務(wù)之間調(diào)用還需要鑒權(quán)?
          ??Java8——方法引用
          ??Java8——Stream流
          ??Spring Boot讀取配置文件的幾種方式
          ??API接口設(shè)計(jì)規(guī)范


          瀏覽 17
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉色老板 | 五月丁香黄色电影 | 国产成人AV导航 | 国产九九九在线观看 | 日韩一级a免费在线视频 |