人人都懂密碼學(xué)】一篇最易懂的Java密碼學(xué)入門教程(上) 【人人都懂密碼學(xué)】一篇最易懂的Java密碼學(xué)入門教程(中) 【人人都懂密碼學(xué)】一篇最易懂的Java密碼學(xué)入門教程(下)(JAVA密碼)

      網(wǎng)友投稿 871 2022-05-30

      密碼與我們的生活息息相關(guān),遠(yuǎn)到國家機(jī)密,近到個(gè)人賬戶,我們每天都在跟密碼打交道:

      那么,密碼從何而來?生活中常見的加密是怎么實(shí)現(xiàn)的?怎么保證個(gè)人信息安全?本文將從這幾方面進(jìn)行淺談,如有紕漏,敬請(qǐng)各位大佬指正。

      代碼部分從第二章節(jié)——常見加密算法開始,對(duì)代碼比較感興趣的鐵子們可以從第二章節(jié)開始看。

      一、 密碼學(xué)發(fā)展史

      密碼學(xué)是網(wǎng)絡(luò)安全、信息安全、區(qū)塊鏈等產(chǎn)品的基礎(chǔ),常見的非對(duì)稱加密、對(duì)稱加密、散列函數(shù)等,都屬于密碼學(xué)范疇。

      密碼學(xué)有數(shù)千年的歷史,從最開始的替換法到如今的非對(duì)稱加密算法,經(jīng)歷了古典密碼學(xué),近代密碼學(xué)和現(xiàn)代密碼學(xué)三個(gè)階段。密碼學(xué)不僅僅是數(shù)學(xué)家們的智慧,更是如今網(wǎng)絡(luò)空間安全的重要基礎(chǔ)。

      1.1 古典密碼學(xué)

      古典密碼的加密方式主要有替換法和移位法。古典密碼雖然很簡單,但是在密碼史上是使用的最久的加密方式,直到“概率論”的數(shù)學(xué)方法被發(fā)現(xiàn),古典密碼就被破解了。

      1.2 近代密碼學(xué)

      古典密碼的安全性受到了威脅,外加使用便利性較低,到了工業(yè)化時(shí)代,近現(xiàn)代密碼被廣泛應(yīng)用。

      恩尼格瑪機(jī)

      恩尼格瑪機(jī)是二戰(zhàn)時(shí)期納粹德國使用的加密機(jī)器,后被英國破譯,參與破譯的人員有被稱為計(jì)算機(jī)科學(xué)之父、人工智能之父的圖靈。

      1.3 現(xiàn)代密碼學(xué)

      ① 散列函數(shù)

      散列函數(shù),也見雜湊函數(shù)、摘要函數(shù)或哈希函數(shù),可將任意長度的消息經(jīng)過運(yùn)算,變成固定長度數(shù)值,常見的有MD5、SHA-1、SHA256,多應(yīng)用在文件校驗(yàn),數(shù)字簽名中。

      【人人都懂密碼學(xué)】一篇最易懂的Java密碼學(xué)入門教程(上) 【人人都懂密碼學(xué)】一篇最易懂的Java密碼學(xué)入門教程(中) 【人人都懂密碼學(xué)】一篇最易懂的Java密碼學(xué)入門教程(下)(JAVA密碼)

      MD5 可以將任意長度的原文生成一個(gè)128位(16字節(jié))的哈希值

      SHA-1可以將任意長度的原文生成一個(gè)160位(20字節(jié))的哈希值

      ② 對(duì)稱密碼

      對(duì)稱密碼應(yīng)用了相同的加密密鑰和解密密鑰。對(duì)稱密碼分為:序列密碼(流密碼),分組密碼(塊密碼)兩種。流密碼是對(duì)信息流中的每一個(gè)元素(一個(gè)字母或一個(gè)比特)作為基本的處理單元進(jìn)行加密,塊密碼是先對(duì)信息流分塊,再對(duì)每一塊分別加密。

      例如原文為1234567890,流加密即先對(duì)1進(jìn)行加密,再對(duì)2進(jìn)行加密,再對(duì)3進(jìn)行加密……最后拼接成密文;塊加密先分成不同的塊,如1234成塊,5678成塊,90XX(XX為補(bǔ)位數(shù)字)成塊,再分別對(duì)不同塊進(jìn)行加密,最后拼接成密文。前文提到的古典密碼學(xué)加密方法,都屬于流加密。

      ③ 非對(duì)稱密碼

      對(duì)稱密碼的密鑰安全極其重要,加密者和解密者需要提前協(xié)商密鑰,并各自確保密鑰的安全性,一但密鑰泄露,即使算法是安全的也無法保障原文信息的私密性。

      在實(shí)際的使用中,遠(yuǎn)程的提前協(xié)商密鑰不容易實(shí)現(xiàn),即使協(xié)商好,在遠(yuǎn)程傳輸過程中也容易被他人獲取,因此非對(duì)稱密鑰此時(shí)就凸顯出了優(yōu)勢(shì)。

      非對(duì)稱密碼有兩支密鑰,公鑰(publickey)和私鑰(privatekey),加密和解密運(yùn)算使用的密鑰不同。用公鑰對(duì)原文進(jìn)行加密后,需要由私鑰進(jìn)行解密;用私鑰對(duì)原文進(jìn)行加密后(此時(shí)一般稱為簽名),需要由公鑰進(jìn)行解密(此時(shí)一般稱為驗(yàn)簽)。公鑰可以公開的,大家使用公鑰對(duì)信息進(jìn)行加密,再發(fā)送給私鑰的持有者,私鑰持有者使用私鑰對(duì)信息進(jìn)行解密,獲得信息原文。因?yàn)樗借€只有單一人持有,因此不用擔(dān)心被他人解密獲取信息原文。

      ________________________________________

      二、常見加密算法

      讓我們來看看生活中常見的幾種加密方式:

      ____________________________________

      2.1 對(duì)稱加密算法

      ________________________________________

      采用單鑰密碼系統(tǒng)的加密方法,同一個(gè)密鑰可以同時(shí)用作信息的加密和解密,這種加密方法稱為對(duì)稱加密,也稱為單密鑰加密。

      示例

      ? 我們現(xiàn)在有一個(gè)原文3要發(fā)送給B

      ? 設(shè)置密鑰為108, 3 * 108 = 324, 將324作為密文發(fā)送給B

      ? B拿到密文324后, 使用324/108 = 3 得到原文

      常見加密算法

      DES : Data Encryption Standard,即數(shù)據(jù)加密標(biāo)準(zhǔn),是一種使用密鑰加密的塊算法,1977年被美國聯(lián)邦政府的國家標(biāo)準(zhǔn)局確定為聯(lián)邦資料處理標(biāo)準(zhǔn)(FIPS),并授權(quán)在非密級(jí)政府通信中使用,隨后該算法在國際上廣泛流傳開來。

      ________________________________________

      AES : Advanced Encryption Standard, 高級(jí)加密標(biāo)準(zhǔn) .在密碼學(xué)中又稱Rijndael加密法,是美國聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)。這個(gè)標(biāo)準(zhǔn)用來替代原先的DES,已經(jīng)被多方分析且廣為全世界所使用。

      特點(diǎn)

      ? 加密速度快, 可以加密大文件

      ? 密文可逆, 一旦密鑰文件泄漏, 就會(huì)導(dǎo)致數(shù)據(jù)暴露

      ? 加密后編碼表找不到對(duì)應(yīng)字符, 出現(xiàn)亂碼

      ? 一般結(jié)合Base64使用

      2.1.1 DES加密

      示例代碼 des加密算法

      Cipher :文檔 https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html#getInstance-java.lang.String-

      import?javax.crypto.Cipher; import?javax.crypto.spec.SecretKeySpec; /** ?* ?* ?*?@author?cWX970190 ?*?@since?2020-10-10?21:50 ?*/ public?class?DesAesDemo?{ ????public?static?void?main(String[]?args)?throws?Exception{ ????????//?原文 ????????String?input?=?"華為"; ????????//?des加密必須是8位 ????????String?key?=?"123456"; ????????//?算法 ????????String?algorithm?=?"DES"; ????????String?transformation?=?"DES"; ????//?Cipher:密碼,獲取加密對(duì)象 ????//?transformation:參數(shù)表示使用什么類型加密 ????Cipher?cipher?=?Cipher.getInstance(transformation); ????//?指定秘鑰規(guī)則 ????//?第一個(gè)參數(shù)表示:密鑰,key的字節(jié)數(shù)組 ????//?第二個(gè)參數(shù)表示:算法 ????SecretKeySpec?sks?=?new?SecretKeySpec(key.getBytes(),?algorithm); ????//?對(duì)加密進(jìn)行初始化 ????//?第一個(gè)參數(shù):表示模式,有加密模式和解密模式 ????//?第二個(gè)參數(shù):表示秘鑰規(guī)則 ????cipher.init(Cipher.ENCRYPT_MODE,sks); ????//?進(jìn)行加密 ????byte[]?bytes?=?cipher.doFinal(input.getBytes()); ????//?打印字節(jié),因?yàn)閍scii碼有負(fù)數(shù),解析不出來,所以亂碼 //????????for?(byte?b?:?bytes)?{ //????????????System.out.println(b); //????????} ????????//?打印密文 ????????System.out.println(new?String(bytes)); ????} }

      運(yùn)行:

      出現(xiàn)這個(gè)bug的原因是DES算法規(guī)定,key必須是8個(gè)字節(jié);

      修改 密鑰 key = “12345678” ,再次運(yùn)行 ,出現(xiàn)亂碼是因?yàn)閷?duì)應(yīng)的字節(jié)出現(xiàn)負(fù)數(shù),但負(fù)數(shù)沒有出現(xiàn)在 ascii 碼表里面,所以出現(xiàn)亂碼,需要配合base64進(jìn)行轉(zhuǎn)碼

      ________________________________________

      2.1.2 拓展:base64編碼

      ________________________________________

      在Java 8中,Base64編碼已經(jīng)成為Java類庫的標(biāo)準(zhǔn)。

      Java 8 內(nèi)置了 Base64 編碼的編碼器和解碼器。

      Base64工具類提供了一套靜態(tài)方法獲取下面三種BASE64編解碼器:

      - 基本:輸出被映射到一組字符A-Za-z0-9+/,編碼不添加任何行標(biāo),輸出的解碼僅支持A-Za-z0-9+/。

      - URL:輸出映射到一組字符A-Za-z0-9+_,輸出是URL和文件。

      - MIME:輸出隱射到MIME友好格式。輸出每行不超過76字符,并且使用’\r’并跟隨’\n’作為分割。編碼輸出最后沒有行分割。

      上面的例子用Java8自帶的base64進(jìn)行編碼:

      import?javax.crypto.Cipher; import?javax.crypto.spec.SecretKeySpec; import?java.util.Base64; /** ?*?DesAesDemo ?* ?*?@Author:?陳志強(qiáng) ?*?@CreateTime:?2020-10-10 ?*?@Description: ?*/ public?class?DesAesDemo?{ ????public?static?void?main(String[]?args)?throws?Exception{ ????????//?原文 ????????String?input?=?"華為"; ????????//?des加密必須是8位 ????????String?key?=?"12345678"; ????????//?算法 ????????String?algorithm?=?"DES"; ????????String?transformation?=?"DES"; ????????//?Cipher:密碼,獲取加密對(duì)象 ????????//?transformation:參數(shù)表示使用什么類型加密 ????????Cipher?cipher?=?Cipher.getInstance(transformation); ????????//?指定秘鑰規(guī)則 ????????//?第一個(gè)參數(shù)表示:密鑰,key的字節(jié)數(shù)組 ????????//?第二個(gè)參數(shù)表示:算法 ????????SecretKeySpec?sks?=?new?SecretKeySpec(key.getBytes(),?algorithm); ????????//?對(duì)加密進(jìn)行初始化 ????????//?第一個(gè)參數(shù):表示模式,有加密模式和解密模式 ????????//?第二個(gè)參數(shù):表示秘鑰規(guī)則 ????????cipher.init(Cipher.ENCRYPT_MODE,sks); ????????//?進(jìn)行加密 ????????byte[]?bytes?=?cipher.doFinal(input.getBytes()); ????????//對(duì)數(shù)據(jù)進(jìn)行base64編碼處理 ????????String?encode?=?Base64.getEncoder().encodeToString(bytes); ????????//?打印密文 ????????System.out.println(encode); ????} }

      運(yùn)行:

      除了上面的編碼方式外,base64還有其他的編碼方式,由于筆者時(shí)間有限,沒有過多研究,在此放入一個(gè)demo,供大家參考:

      import?org.junit.Test; import?java.io.UnsupportedEncodingException; import?java.util.Base64; import?java.util.UUID; /** ?*?在Java?8中,Base64編碼已經(jīng)成為Java類庫的標(biāo)準(zhǔn)。 ?*?Java?8?內(nèi)置了?Base64?編碼的編碼器和解碼器。 ?*?Base64工具類提供了一套靜態(tài)方法獲取下面三種BASE64編解碼器: ?*?

      ?*?基本:輸出被映射到一組字符A-Za-z0-9+/,編碼不添加任何行標(biāo),輸出的解碼僅支持A-Za-z0-9+/。 ?*?URL:輸出被映射到一組字符A-Za-z0-9+_,輸出是URL和文件。 ?*?MIME:輸出隱射到MIME友好格式。輸出每行不超過76字符,并且使用'\r'并跟隨'\n'作為分割。編碼輸出最后沒有行分割。 ?*/ public?class?Base64Test?{ ????private?static?final?String?UTF_8?=?"utf-8"; ????private?static?final?int?MAX?=?10; ????@Test ????public?void?base64()?throws?UnsupportedEncodingException?{ //????????test(); //????????basic(); ????????url(); //????????mime(); ????} ????/** ?????*?測(cè)試幾個(gè)特殊字符 ?????*/ ????private?void?test()?throws?UnsupportedEncodingException?{ ????????String?ss?=?"星期五?/\\|"; ????????System.out.println("ordinal?????????:?"?+?ss); ????????byte[]?encode?=?Base64.getEncoder().encode(ss.getBytes(UTF_8)); ????????System.out.println("basic?encode????:?"?+?new?String(encode,?UTF_8)); ????????byte[]?decode?=?Base64.getDecoder().decode(encode); ????????System.out.println("Using?Basic?????:?"?+?new?String(decode,?UTF_8)); ????????byte[]?decode1?=?Base64.getUrlDecoder().decode(encode); ????????System.out.println("Using?URL???????:?"?+?new?String(decode1,?UTF_8)); ????????byte[]?decode2?=?Base64.getMimeDecoder().decode(encode); ????????System.out.println("Using?MIME??????:?"?+?new?String(decode2,?UTF_8)); ????????System.out.println(); ????} ????/** ?????*?MIME編碼器會(huì)使用基本的字母數(shù)字產(chǎn)生BASE64輸出, ?????*?而且對(duì)MIME格式友好:每一行輸出不超過76個(gè)字符,而且每行以“\r\n”符結(jié)束 ?????*/ ????private?void?mime()?throws?UnsupportedEncodingException?{ ????????StringBuilder?sb?=?new?StringBuilder(); ????????for?(int?t?=?0;?t?

      運(yùn)行:

      2.1.3 DES解密

      在2.1.1中的例子基礎(chǔ)上加入解密方法

      import?javax.crypto.Cipher; import?javax.crypto.spec.SecretKeySpec; import?java.util.Base64; public?class?DesDemo?{ ????//?DES加密算法,key的大小必須是8個(gè)字節(jié) public?static?void?main(String[]?args)?throws?Exception?{ ????String?input?="華為"; ????//?DES加密算法,key的大小必須是8個(gè)字節(jié) ????String?key?=?"12345678"; ????String?transformation?=?"DES";?//?9PQXVUIhaaQ= ????//?指定獲取密鑰的算法 ????String?algorithm?=?"DES"; ????String?encryptDES?=?encryptDES(input,?key,?transformation,?algorithm); ????System.out.println("加密:"?+?encryptDES); ????String?s?=?decryptDES(encryptDES,?key,?transformation,?algorithm); ????System.out.println("解密:"?+?s); } /** ?*?使用DES加密數(shù)據(jù) ?* ?*?@param?input??????????:?原文 ?*?@param?key????????????:?密鑰(DES,密鑰的長度必須是8個(gè)字節(jié)) ?*?@param?transformation?:?獲取Cipher對(duì)象的算法 ?*?@param?algorithm??????:?獲取密鑰的算法 ?*?@return?:?密文 ?*?@throws?Exception ?*/ private?static?String?encryptDES(String?input,?String?key,?String?transformation,?String?algorithm)?throws?Exception?{ ????//?獲取加密對(duì)象 ????Cipher?cipher?=?Cipher.getInstance(transformation); ????//?創(chuàng)建加密規(guī)則 ????//?第一個(gè)參數(shù)key的字節(jié) ????//?第二個(gè)參數(shù)表示加密算法 ????SecretKeySpec?sks?=?new?SecretKeySpec(key.getBytes(),?algorithm); ????//?ENCRYPT_MODE:加密模式 ????//?DECRYPT_MODE:?解密模式 ????//?初始化加密模式和算法 ????cipher.init(Cipher.ENCRYPT_MODE,sks); ????//?加密 ????byte[]?bytes?=?cipher.doFinal(input.getBytes()); ????//?輸出加密后的數(shù)據(jù) ????String?encode?=?new?String(Base64.getEncoder().encode(bytes),?"UTF-8"); //????????System.out.println(encode); ????????return?encode; ????} /** ?*?使用DES解密 ?* ?*?@param?input??????????:?密文 ?*?@param?key????????????:?密鑰 ?*?@param?transformation?:?獲取Cipher對(duì)象的算法 ?*?@param?algorithm??????:?獲取密鑰的算法 ?*?@throws?Exception ?*?@return:?原文 ?*/ private?static?String?decryptDES(String?input,?String?key,?String?transformation,?String?algorithm)?throws?Exception?{ ????//?1,獲取Cipher對(duì)象 ????Cipher?cipher?=?Cipher.getInstance(transformation); ????//?指定密鑰規(guī)則 ????SecretKeySpec?sks?=?new?SecretKeySpec(key.getBytes(),?algorithm); ????cipher.init(Cipher.DECRYPT_MODE,?sks); ????//?3.?解密,上面使用的base64編碼,下面直接用密文 ????byte[]?bytes?=?cipher.doFinal(Base64.getDecoder().decode(input)); //????????System.out.println("解密"?+?new?String(decode,?"UTF-8")); ????????//??因?yàn)槭敲魑模灾苯臃祷?????????return?new?String(bytes); ????} }

      運(yùn)行:

      2.1.4 AES加密解密

      AES 加密解密和 DES 加密解密代碼一樣,只需要修改加密算法就行,在此不做過多闡述,值得注意的是:AES 加密的密鑰key , 需要傳入16個(gè)字節(jié).

      2.1.5 加密模式

      AES的加密模式如下:

      參考鏈接:https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html

      這里主要介紹兩種加密模式:ECB和CBC

      ECB

      Electronic codebook, 電子密碼本. 需要加密的消息按照塊密碼的塊大小被分為數(shù)個(gè)塊,并對(duì)每個(gè)塊進(jìn)行獨(dú)立加密

      ? 優(yōu)點(diǎn) : 可以并行處理數(shù)據(jù)

      ? 缺點(diǎn) : 同樣的原文生成同樣的密文, 不能很好的保護(hù)數(shù)據(jù)

      ? 同時(shí)加密,原文是一樣的,加密出來的密文也是一樣的

      CBC

      Cipher-block chaining, 密碼塊鏈接. 每個(gè)明文塊先與前一個(gè)密文塊進(jìn)行異或后,再進(jìn)行加密。在這種方法中,每個(gè)密文塊都依賴于它前面的所有明文塊

      ? 優(yōu)點(diǎn) : 同樣的原文生成的密文不一樣

      ? 缺點(diǎn) : 串行處理數(shù)據(jù).

      2.1.6 填充模式

      當(dāng)需要按塊處理的數(shù)據(jù), 數(shù)據(jù)長度不符合塊處理需求時(shí), 按照一定的方法填充滿塊長的規(guī)則,這里主要介紹以下兩種:

      NoPadding

      ? 不填充.

      ? 在DES加密算法下, 要求原文長度必須是8byte的整數(shù)倍

      ? 在AES加密算法下, 要求原文長度必須是16byte的整數(shù)倍

      PKCS5Padding

      ? 數(shù)據(jù)塊的大小為8位, 不夠就補(bǔ)足

      Tips

      ? 默認(rèn)情況下, 加密模式和填充模式為 : ECB/PKCS5Padding

      ? 如果使用CBC模式, 在初始化Cipher對(duì)象時(shí), 需要增加參數(shù), 初始化向量IV : IvParameterSpec iv = new IvParameterSpec(key.getBytes());

      加密模式和填充模式:其中括號(hào)里數(shù)字表示加密位數(shù),位數(shù)越高,則越安全

      AES/CBC/NoPadding?(128) AES/CBC/PKCS5Padding?(128) AES/ECB/NoPadding?(128) AES/ECB/PKCS5Padding?(128) DES/CBC/NoPadding?(56) DES/CBC/PKCS5Padding?(56) DES/ECB/NoPadding?(56) DES/ECB/PKCS5Padding?(56) DESede/CBC/NoPadding?(168) DESede/CBC/PKCS5Padding?(168) DESede/ECB/NoPadding?(168) DESede/ECB/PKCS5Padding?(168) RSA/ECB/PKCS1Padding?(1024,?2048) RSA/ECB/OAEPWithSHA-1AndMGF1Padding?(1024,?2048) RSA/ECB/OAEPWithSHA-256AndMGF1Padding?(1024,?2048)

      加密模式和填充模式例子

      /* ?*?Copyright?(c)?Huawei?Technologies?Co.,?Ltd.?2020-2020.?All?rights?reserved. ?*/ package?com.huawei.it.jalor.boot.test; /** ?*?功能描述:?加密模式和填充模式例子 ?* ?*?@author?cWX970190 ?*?@since?2020-10-11 ?*/ import?com.sun.org.apache.xml.internal.security.utils.Base64; import?javax.crypto.Cipher; import?javax.crypto.spec.SecretKeySpec; public?class?DesDemo?{ ????//?DES加密算法,key的大小必須是8個(gè)字節(jié) ????public?static?void?main(String[]?args)?throws?Exception?{ ????????String?input?="華為"; ????????//?DES加密算法,key的大小必須是8個(gè)字節(jié) ????????String?key?=?"12345678"; ????????//?指定獲取Cipher的算法,如果沒有指定加密模式和填充模式,ECB/PKCS5Padding就是默認(rèn)值 ????????//?????String?transformation?=?"DES";?//?9PQXVUIhaaQ= ????????//String?transformation?=?"DES/ECB/PKCS5Padding";?//?9PQXVUIhaaQ= ????????//?CBC模式,必須指定初始向量,初始向量中密鑰的長度必須是8個(gè)字節(jié) //????????String?transformation?=?"DES/CBC/PKCS5Padding";?//?9PQXVUIhaaQ= ????????//?NoPadding模式,原文的長度必須是8個(gè)字節(jié)的整倍數(shù)?,所以必須把?硅谷改成硅谷12 ????????String?transformation?=?"DES/CBC/NoPadding";?//?9PQXVUIhaaQ= ????????//?指定獲取密鑰的算法 ????????String?algorithm?=?"DES"; ????????String?encryptDES?=?encryptDES(input,?key,?transformation,?algorithm); ????????System.out.println("加密:"?+?encryptDES); ????????String?s?=?dncryptDES(encryptDES,?key,?transformation,?algorithm); ????????System.out.println("解密:"?+?s); ????} ????/** ?????*?使用DES加密數(shù)據(jù) ?????* ?????*?@param?input??????????:?原文 ?????*?@param?key????????????:?密鑰(DES,密鑰的長度必須是8個(gè)字節(jié)) ?????*?@param?transformation?:?獲取Cipher對(duì)象的算法 ?????*?@param?algorithm??????:?獲取密鑰的算法 ?????*?@return?:?密文 ?????*?@throws?Exception ?????*/ ????private?static?String?encryptDES(String?input,?String?key,?String?transformation,?String?algorithm)?throws?Exception?{ ????????//?獲取加密對(duì)象 ????????Cipher?cipher?=?Cipher.getInstance(transformation); ????????//?創(chuàng)建加密規(guī)則 ????????//?第一個(gè)參數(shù)key的字節(jié) ????????//?第二個(gè)參數(shù)表示加密算法 ????????SecretKeySpec?sks?=?new?SecretKeySpec(key.getBytes(),?algorithm); ????????//?ENCRYPT_MODE:加密模式 ????????//?DECRYPT_MODE:?解密模式 ????????//?初始向量,參數(shù)表示跟誰進(jìn)行異或,初始向量的長度必須是8位 //????????IvParameterSpec?iv?=?new?IvParameterSpec(key.getBytes()); ????????//?初始化加密模式和算法 ????????cipher.init(Cipher.ENCRYPT_MODE,sks); ????????//?加密 ????????byte[]?bytes?=?cipher.doFinal(input.getBytes()); ????????//?輸出加密后的數(shù)據(jù) ????????String?encode?=?Base64.encode(bytes); ????????return?encode; ????} ????/** ?????*?使用DES解密 ?????* ?????*?@param?input??????????:?密文 ?????*?@param?key????????????:?密鑰 ?????*?@param?transformation?:?獲取Cipher對(duì)象的算法 ?????*?@param?algorithm??????:?獲取密鑰的算法 ?????*?@throws?Exception ?????*?@return:?原文 ?????*/ ????private?static?String?dncryptDES(String?input,?String?key,?String?transformation,?String?algorithm)?throws?Exception?{ ????????//?1,獲取Cipher對(duì)象 ????????Cipher?cipher?=?Cipher.getInstance(transformation); ????????//?指定密鑰規(guī)則 ????????SecretKeySpec?sks?=?new?SecretKeySpec(key.getBytes(),?algorithm); //????????IvParameterSpec?iv?=?new?IvParameterSpec(key.getBytes()); ????????cipher.init(Cipher.DECRYPT_MODE,?sks); ????????//?3.?解密 ????????byte[]?bytes?=?cipher.doFinal(Base64.decode(input)); ????????return?new?String(bytes); ????} }

      運(yùn)行:

      非填充模式下,原文必須是8個(gè)字節(jié),修改加密模式為:

      String?transformation?=?"DES/CBC/PKCS5Padding";

      再次運(yùn)行:

      發(fā)現(xiàn)加密沒有問題,但是解密時(shí)需要添加一個(gè)參數(shù),添加參數(shù)并修改初始化規(guī)則:

      //?初始向量,參數(shù)表示跟誰進(jìn)行異或,初始向量的長度必須是8位 ????????IvParameterSpec?iv?=?new?IvParameterSpec(key.getBytes()); ????????//?初始化加密模式和算法 ????????cipher.init(Cipher.ENCRYPT_MODE,sks,iv);

      再次運(yùn)行:

      在測(cè)試 AES 的時(shí)候需要注意,key需要16個(gè)字節(jié),加密向量也需要16個(gè)字節(jié) ,其他方式跟 DES 一樣

      ________________________________________

      2.2 消息摘要(單向散列)函數(shù)

      ________________________________________

      ? 消息摘要(Message Digest)又稱為數(shù)字摘要(Digital Digest)

      ? 它是一個(gè)唯一對(duì)應(yīng)一個(gè)消息或文本的固定長度的值,它由一個(gè)單向Hash加密函數(shù)對(duì)消息進(jìn)行作用而產(chǎn)生

      ? 使用數(shù)字摘要生成的值是不可以篡改的,為了保證文件或者值的安全

      2.2.1 特點(diǎn)

      無論輸入的消息有多長,計(jì)算出來的消息摘要的長度總是固定的。例如應(yīng)用MD5算法摘要的消息有128個(gè)比特位,用SHA-1算法摘要的消息最終有160比特位的輸出

      只要輸入的消息不同,對(duì)其進(jìn)行摘要以后產(chǎn)生的摘要消息也必不相同;但相同的輸入必會(huì)產(chǎn)生相同的輸出

      消息摘要是單向、不可逆的

      常見算法 :

      ? MD5

      ? SHA1

      ? SHA256

      ? SHA512

      瀏覽器搜索 tomcat ,進(jìn)入官網(wǎng)下載 ,會(huì)經(jīng)常發(fā)現(xiàn)有 sha1,sha512 , 這些都是數(shù)字摘要

      2.2.2 獲取字符串消息摘要

      /* ?*?Copyright?(c)?Huawei?Technologies?Co.,?Ltd.?2020-2020.?All?rights?reserved. ?*/ package?com.huawei.it.jalor.boot.test; /** ?*?功能描述 ?* ?*?@author?cWX970190 ?*?@since?2020-10-11 ?*/ import?com.sun.org.apache.xml.internal.security.utils.Base64; import?java.security.MessageDigest; public?class?DigestDemo1?{ ????public?static?void?main(String[]?args)?throws?Exception{ ????????//?原文 ????????String?input?=?"aa"; ????????//?算法 ????????String?algorithm?=?"MD5"; ????????//?獲取數(shù)字摘要對(duì)象 ????????MessageDigest?messageDigest?=?MessageDigest.getInstance(algorithm); ????????//?獲取消息數(shù)字摘要的字節(jié)數(shù)組 ????????byte[]?digest?=?messageDigest.digest(input.getBytes("UTF-8")); ????????//需要進(jìn)行base64編碼,不然輸出亂碼 ????????System.out.println(Base64.encode(digest)); ????} }

      運(yùn)行:

      使用在線 md5 加密 ,發(fā)現(xiàn)我們生成的值和代碼生成的值不一樣,那是因?yàn)橄⒄皇鞘褂胋ase64進(jìn)行編碼的,所以我們需要把值轉(zhuǎn)成16進(jìn)制

      數(shù)字摘要轉(zhuǎn)換成 16 進(jìn)制

      package?com.huawei.it.jalor.boot.test; /** ?*?功能描述 ?* ?*?@author?cWX970190 ?*?@since?2020-10-11 ?*/ import?com.sun.org.apache.xml.internal.security.utils.Base64; import?java.security.MessageDigest; public?class?DigestDemo1?{ ????public?static?void?main(String[]?args)?throws?Exception{ ????????//?原文 ????????String?input?=?"aa"; ????????//?算法 ????????String?algorithm?=?"MD5"; ????????//?獲取數(shù)字摘要對(duì)象 ????????MessageDigest?messageDigest?=?MessageDigest.getInstance(algorithm); ????????//?獲取消息數(shù)字摘要的字節(jié)數(shù)組 ????????byte[]?digest?=?messageDigest.digest(input.getBytes("UTF-8")); ????????//????????System.out.println(new?String(digest)); ????????//?base64編碼 //????????System.out.println(Base64.encode(digest)); ????????//?創(chuàng)建對(duì)象用來拼接 ????????StringBuilder?sb?=?new?StringBuilder(); ????????for?(byte?b?:?digest)?{ ????????????//?轉(zhuǎn)成?16進(jìn)制 ????????????String?s?=?Integer.toHexString(b?&?0xff); ????????????//System.out.println(s); ????????????if?(s.length()?==?1){ ????????????????//?如果生成的字符只有一個(gè),前面補(bǔ)0 ????????????????s?=?"0"+s; ????????????} ????????????sb.append(s); ????????} ????????System.out.println(sb.toString()); ????} }

      運(yùn)行,結(jié)果和在線一致:

      2.2.3 其他消息摘要算法

      /** ?*?功能描述 ?* ?*?@author?cWX970190 ?*?@since?2020-10-11 ?*/ import?java.security.MessageDigest; /** ?*?DigestDemo1 ?* ?*?@Author:?陳志強(qiáng) ?*?@CreateTime:?2020-03-17 ?*?@Description: ?*/ public?class?DigestDemo1?{ ????public?static?void?main(String[]?args)?throws?Exception{ ????????//?4124bc0a9335c27f086f24ba207a4912?????md5?在線校驗(yàn) ????????//?QSS8CpM1wn8IbyS6IHpJEg==?????????????消息摘要使用的是16進(jìn)制 ????????//?原文 ????????String?input?=?"aa"; ????????//?算法 ????????String?algorithm?=?"MD5"; ????????//?獲取數(shù)字摘要對(duì)象 ????????String?md5?=?getDigest(input,?"MD5"); ????????System.out.println(md5); ????????String?sha1?=?getDigest(input,?"SHA-1"); ????????System.out.println(sha1); ????????String?sha256?=?getDigest(input,?"SHA-256"); ????????System.out.println(sha256); ????????String?sha512?=?getDigest(input,?"SHA-512"); ????????System.out.println(sha512); ????} ????private?static?String?toHex(byte[]?digest)?throws?Exception?{ //????????System.out.println(new?String(digest)); ????????//?base64編碼 //????????System.out.println(Base64.encode(digest)); ????????//?創(chuàng)建對(duì)象用來拼接 ????????StringBuilder?sb?=?new?StringBuilder(); ????????for?(byte?b?:?digest)?{ ????????????//?轉(zhuǎn)成?16進(jìn)制 ????????????String?s?=?Integer.toHexString(b?&?0xff); ????????????if?(s.length()?==?1){ ????????????????//?如果生成的字符只有一個(gè),前面補(bǔ)0 ????????????????s?=?"0"+s; ????????????} ????????????sb.append(s); ????????} ????????System.out.println("16進(jìn)制數(shù)據(jù)的長度:"?+?sb.toString().getBytes().length); ????????return?sb.toString(); ????} ????private?static?String?getDigest(String?input,?String?algorithm)?throws?Exception?{ ????????MessageDigest?messageDigest?=?MessageDigest.getInstance(algorithm); ????????//?消息數(shù)字摘要 ????????byte[]?digest?=?messageDigest.digest(input.getBytes()); ????????System.out.println("密文的字節(jié)長度:"?+?digest.length); ????????return?toHex(digest); ????} }

      運(yùn)行:

      ----未完,待續(xù)---

      【人人都懂密碼學(xué)】一篇最易懂的Java密碼學(xué)入門教程(中)

      【人人都懂密碼學(xué)】一篇最易懂的Java密碼學(xué)入門教程(下)

      Java

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:關(guān)于Linux性能調(diào)優(yōu)中網(wǎng)絡(luò)I/O的一些筆記(linux網(wǎng)絡(luò)性能優(yōu)化)
      下一篇:【吐血推薦】領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)學(xué)習(xí)輸出(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)入門)
      相關(guān)文章
      国产成人亚洲综合在线| 久久亚洲精品成人| 亚洲狠狠综合久久| 亚洲国产精品成人一区| 亚洲乱人伦中文字幕无码| 亚洲天堂在线播放| 911精品国产亚洲日本美国韩国| 亚洲国产成人私人影院| 亚洲免费视频在线观看| 亚洲人成电影在在线观看网色| 亚洲成人影院在线观看| 亚洲精品成a人在线观看| 亚洲性久久久影院| 亚洲一区二区三区AV无码| 亚洲精品中文字幕乱码三区| 国产亚洲精品自在久久| 亚洲AV无码久久精品狠狠爱浪潮| 国产∨亚洲V天堂无码久久久| 久久被窝电影亚洲爽爽爽| 亚洲AV无码成人精品区蜜桃 | 亚洲国产精品久久久久婷婷老年 | 亚洲熟妇AV乱码在线观看| 亚洲日本人成中文字幕| 亚洲综合色婷婷在线观看| 亚洲精品天堂成人片AV在线播放| 亚洲乱码无人区卡1卡2卡3| 亚洲av无码专区青青草原| 亚洲国产aⅴ综合网| 伊人久久综在合线亚洲91| 亚洲国产精品高清久久久| 亚洲综合久久综合激情久久| 亚洲第一网站免费视频| 亚洲午夜精品国产电影在线观看| 亚洲人成人网毛片在线播放| 亚洲精华国产精华精华液好用 | 国产AV无码专区亚洲AVJULIA | 亚洲精品在线免费看| 亚洲免费视频在线观看| 亚洲AV日韩精品久久久久| 亚洲精品一品区二品区三品区| 亚洲?V乱码久久精品蜜桃|