0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

對于加解密、加簽驗簽?zāi)銈冇懈拍顔?/h1>

面對MD5、SHA、DES、AES、RSA等等這些名詞你是否有很多問號?這些名詞都是什么?還有什么公鑰加密、私鑰解密、私鑰加簽、公鑰驗簽。這些都什么鬼?或許在你日常工作沒有聽說過這些名詞,但是一旦你要設(shè)計一個對外訪問的接口,或者安全性要求高的系統(tǒng),那么必然會接觸到這些名詞。

所以加解密、加簽驗簽對于一個合格的程序員來說是必須要掌握的一個概念。那么加解密相關(guān)的密碼學(xué)真的離我們很遙遠(yuǎn)嗎?其實生活中有很多常見的場景其實都用到了密碼學(xué)的相關(guān)知識,我們不要把它想得太難。

例如在《睡在我上鋪的兄弟》這一段中作弊繞口令中,小癟三代表A,小赤佬代表B,唉呀媽呀代表C,坑爹呀是D,這一段繞口令其實也是密碼學(xué)的一種。有興趣的小伙伴可以看一下這一片段繞口令片段(https://www.bilibili.com/video/av3696396/)。所以其實密碼學(xué)與我們生活息息相關(guān),接下來我們就一文徹底搞懂這些概念。

沒有硝煙的戰(zhàn)場——淺談密碼技術(shù)

沒有根基也許可以建一座小屋,但絕對不能造一座堅固的大廈。

密碼這個詞有很多種的解釋,在現(xiàn)代社會如果不接觸編程的話,那么普遍的認(rèn)為是我們設(shè)置的登錄密碼、或者是去銀行取錢時輸入的數(shù)字。都是我們在注冊時實現(xiàn)給提供服務(wù)的一方存儲一組數(shù)字,以后我們登錄的時候就用這組數(shù)字相當(dāng)于就證明了我們的身份。這個數(shù)字通常來說就是叫做密碼。而我們需要了解的不是上面說的密碼,而是一種“密碼術(shù)”,就是對于要傳遞的信息按照某種規(guī)則進(jìn)行轉(zhuǎn)換,從而隱藏信息的內(nèi)容。這種方法可以使機(jī)密信息得以在公開的渠道傳遞而不泄密。使用這種方法,要經(jīng)過加密過程。在加密過程中我們需要知道下面的這些概念:

原文:或者叫明文,就是被隱藏的文字

加密法:指隱藏原文的法則

密文:或者叫偽文,指對原文按照加密法處理過后生成的可公開傳遞的文字

密鑰:在加密法中起決定性的因素,可能是數(shù)字、詞匯,也可能是一些字母,或者這些東西的組合

加密的結(jié)果生成了密文,要想讓接受者能夠讀懂這些密文,那么就要把加密法以及密鑰告訴接受者,否者接受者無法對密文解密,也就無法讀懂原文。從歷史的角度來看,密碼學(xué)大概可以分為古典密碼學(xué)和近現(xiàn)代密碼學(xué)兩個階段。兩者以現(xiàn)代信息技術(shù)的誕生為分界點,現(xiàn)在所討論的密碼學(xué)多指的是后者,建立在信息論和數(shù)學(xué)成果基礎(chǔ)之上的。

古典密碼學(xué)

古典密碼學(xué)源自于數(shù)千年前,最早在公元前1900年左右的古埃及,就出現(xiàn)了通過使用特殊字符和簡單替換式密碼來保護(hù)信息。美索不達(dá)米亞平原上曾經(jīng)出土一個公元前1500年左右的泥板,其上記錄了加密描述的陶瓷器上釉的工藝配方。

古希臘時期(公元前800 ﹣前146 年)還發(fā)明了通過物理手段來隱藏信息的“隱寫術(shù)”,例如使用牛奶書寫、用蠟覆蓋文字等。后來在古羅馬時期還出現(xiàn)了基于替換加密的凱撒密碼,據(jù)稱凱撒曾用此方法與其部下通信而得以命名。

這些手段多數(shù)是采用簡單的機(jī)械工具來保護(hù)秘密,在今天看來毫無疑問是十分簡陋,很容易猜出來的。嚴(yán)格來看,可能都很難稱為密碼科學(xué)。凱撒密碼是當(dāng)偏移量是3的時候,所有的字母都A都將被替換成D,B變成E,以此類推。

近代密碼學(xué)

近代密碼學(xué)的研究來自于第一、二次世界大戰(zhàn)中對于軍事通信進(jìn)行保護(hù)和猜出來的需求。1901年12月,意大利的工程師Guglielmo Marconi(奎里亞摩?馬可尼)成功完成了跨越大西洋的無線電通信的實驗,在全球范圍內(nèi)引發(fā)轟動,推動了無線電通信時代的到來。

無線電大大提高了遠(yuǎn)程通信的能力,但是它有一個天然的缺陷——很難限制接收方,這就意味著你所傳的信息有可能被攔截,因此就催生了加密技術(shù)的發(fā)展。對于無線電信息進(jìn)行加密和解密也直接促進(jìn)了近現(xiàn)代密碼學(xué)和計算機(jī)技術(shù)的出現(xiàn)。反過來這些科技進(jìn)步也影響了時代的發(fā)展。一戰(zhàn)時期德國外交部長Arthur Zimmermann(阿瑟?齊默爾曼)拉攏墨西哥構(gòu)成抗美軍事同盟的電報(1917 年1月16日)被英國情報機(jī)構(gòu)—40號辦公室破譯,直接導(dǎo)致了美國的參戰(zhàn);

二戰(zhàn)時期德國使用的恩尼格瑪(Enigma)密碼機(jī)(當(dāng)時最先進(jìn)的加密設(shè)備)被盟軍成功破譯(1939年到1941年),導(dǎo)致大西洋戰(zhàn)役德國失敗。據(jù)稱,二戰(zhàn)時期光英國從事密碼學(xué)研究的人員就達(dá)到7000人,而他們的成果使二戰(zhàn)結(jié)束的時間至少提前了一到兩年時間。接下來就是可以稱之為是密碼學(xué)發(fā)展史上里程碑的事件了。

1945年9月1日,Claude Elwood Shannon(克勞德?艾爾伍德?香農(nóng))完成了劃時代的內(nèi)部報告《A Mathematical Theory of Cryptography(密碼術(shù)的一個數(shù)學(xué)理論)》,1949 年 10 月,該報告以《Communication Theory of Secrecy Systems(保密系統(tǒng)的通信理論)》為題在 Bell System Technical Journal(貝爾系統(tǒng)技術(shù)期刊)上正式發(fā)表。

這篇論文首次將密碼學(xué)和信息論聯(lián)系到一起,為對稱密碼技術(shù)提供了數(shù)學(xué)基礎(chǔ)。這也標(biāo)志著近現(xiàn)代密碼學(xué)的正式建立。這也是密碼學(xué)發(fā)展史上的第一座里程碑性事件。密碼學(xué)發(fā)展史上的第二個里程碑性事件是DES的出現(xiàn)。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)在非密級政府通信中使用,隨后該算法在國際上廣泛流傳開來。密碼學(xué)發(fā)展史上的第三個里程碑性事件就是我們區(qū)塊鏈中廣泛應(yīng)用的公鑰密碼,也就是非對稱密碼算法的出現(xiàn)。

1976年11月,Whitfield Diffie 和 Martin E.Hellman 在 IEEE Transactions on Information Theory 上發(fā)表了論文《New Directions in Cryptography(密碼學(xué)的新方向)》,探討了無需傳輸密鑰的保密通信和簽名認(rèn)證體系問題,正式開創(chuàng)了現(xiàn)代公鑰密碼學(xué)體系的研究。

在公鑰密碼發(fā)現(xiàn)以前,如果需要保密通信,通信雙方事先要對加解密的算法以及要使用的密鑰進(jìn)行事先協(xié)商,包括送雞毛信,實際上是在傳送密鑰。但自從有了公鑰密碼,需要進(jìn)行秘密通信的雙方不再需要進(jìn)行事前的密鑰協(xié)商了。

公鑰密碼在理論上是不保密的,在實際上是保密的。也就是說,公鑰密碼是可以猜出來的,但需要極長的時間,等到猜出來了,這個秘密也沒有保密的必要了。上面我們說到了關(guān)于近現(xiàn)代的密碼學(xué)相關(guān)的東西,基本上總結(jié)下來我們現(xiàn)在常用的就兩個,一個是對稱加密算法,一個是非對稱加密算法。那么接下來我們就以介紹這兩個概念為主線引出開題中我們提到的概念。

程序?qū)崿F(xiàn)

對稱加密算法

對稱加密指的就是加密和解密使用同一個秘鑰,所以叫做對稱加密。對稱加密只有一個秘鑰,作為私鑰。具體的算法有:DES、3DES、TDEA、Blowfish,RC5,IDEA。但是我們常見的有:DES、AES等等。那么對稱加密的優(yōu)點是什么呢?算法公開、計算量小、加密速度快、加密效率高。缺點就是秘鑰的管理和分發(fā)是非常困難的,不夠安全。在數(shù)據(jù)傳送前,發(fā)送方和接收方必須商定好秘鑰,然后雙方都必須要保存好秘鑰。

如果一方的秘鑰被泄露了,那么加密的信息也就不安全了。另外,每對用戶每次使用對稱加密算法時,都需要使用其他人不知道的唯一秘鑰,這會使得收、發(fā)雙方所擁有的的鑰匙數(shù)量巨大,秘鑰管理也會成為雙方的負(fù)擔(dān)。加密的過程我們可以理解為如下:

加密:原文+秘鑰 = 密文

解密:密文-秘鑰 = 原文

可以看到兩次過程使用的都是一個秘鑰。

實戰(zhàn)演練

既然我們知道關(guān)于對稱加密算法的相關(guān)知識,那么我們?nèi)粘S?a href="http://www.ttokpm.com/v/tag/852/" target="_blank">Java如何實現(xiàn)對稱加密的加密和解密動作呢?常見的對稱加密算法有:DES、AES等。

DES

DES加密算法是一種分組密碼,以64位為分組對數(shù)據(jù)加密,它的密鑰長度是56位,加密解密用同一算法。DES加密算法是對密鑰進(jìn)行保密,而公開算法,包括加密和解密算法。

這樣,只有掌握了和發(fā)送方相同密鑰的人才能解讀由DES加密算法加密的密文數(shù)據(jù)。因此,破譯DES加密算法實際上就是搜索密鑰的編碼。對于56位長度的密鑰來說,如果用窮舉法來進(jìn)行搜索的話,其運(yùn)算次數(shù)為2的56次方。接下來用Java實現(xiàn)DES加密

private final static String DES = “DES”; public static void main(String[] args) throws Exception { String data = “123 456”; String key = “wang!@#$”; System.err.println(encrypt(data, key)); System.err.println(decrypt(encrypt(data, key), key)); } /** * Description 根據(jù)鍵值進(jìn)行加密 * @param data * @param key 加密鍵byte數(shù)組 * @return * @throws Exception */ public static String encrypt(String data, String key) throws Exception { byte[] bt = encrypt(data.getBytes(), key.getBytes()); String strs = new BASE64Encoder().encode(bt); return strs; } /** * Description 根據(jù)鍵值進(jìn)行解密 * @param data * @param key 加密鍵byte數(shù)組 * @return * @throws IOException * @throws Exception */ public static String decrypt(String data, String key) throws IOException, Exception { if (data == null) return null; BASE64Decoder decoder = new BASE64Decoder(); byte[] buf = decoder.decodeBuffer(data); byte[] bt = decrypt(buf,key.getBytes()); return new String(bt); } /** * Description 根據(jù)鍵值進(jìn)行加密 * @param data * @param key 加密鍵byte數(shù)組 * @return * @throws Exception */ private static byte[] encrypt(byte[] data, byte[] key) throws Exception { // 生成一個可信任的隨機(jī)數(shù)源 SecureRandom sr = new SecureRandom(); // 從原始密鑰數(shù)據(jù)創(chuàng)建DESKeySpec對象 DESKeySpec dks = new DESKeySpec(key); // 創(chuàng)建一個密鑰工廠,然后用它把DESKeySpec轉(zhuǎn)換成SecretKey對象 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES); SecretKey securekey = keyFactory.generateSecret(dks); // Cipher對象實際完成加密操作 Cipher cipher = Cipher.getInstance(DES); // 用密鑰初始化Cipher對象 cipher.init(Cipher.ENCRYPT_MODE, securekey, sr); return cipher.doFinal(data); } /** * Description 根據(jù)鍵值進(jìn)行解密 * @param data * @param key 加密鍵byte數(shù)組 * @return * @throws Exception */ private static byte[] decrypt(byte[] data, byte[] key) throws Exception { // 生成一個可信任的隨機(jī)數(shù)源 SecureRandom sr = new SecureRandom(); // 從原始密鑰數(shù)據(jù)創(chuàng)建DESKeySpec對象 DESKeySpec dks = new DESKeySpec(key); // 創(chuàng)建一個密鑰工廠,然后用它把DESKeySpec轉(zhuǎn)換成SecretKey對象 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES); SecretKey securekey = keyFactory.generateSecret(dks); // Cipher對象實際完成解密操作 Cipher cipher = Cipher.getInstance(DES); // 用密鑰初始化Cipher對象 cipher.init(Cipher.DECRYPT_MODE, securekey, sr); return cipher.doFinal(data); }輸出以后可以看到數(shù)據(jù)被加密了

5fiw/XhRJ0E= 123 456在Java中用DES加密有一個特殊的地方

秘鑰設(shè)置的長度必須大于等于8

秘鑰設(shè)置的長度如果大于8的話,那么只會取前8個字節(jié)作為秘鑰

為什么呢,我們可以看到在初始化DESKeySpec類的時候有下面一段,其中var1是我們傳的秘鑰??梢钥吹剿M(jìn)行了截取。只截取前八個字節(jié)。

public DESKeySpec(byte[] var1, int var2) throws InvalidKeyException { if (var1.length - var2 《 8) { throw new InvalidKeyException(“Wrong key size”); } else { this.key = new byte[8]; System.arraycopy(var1, var2, this.key, 0, 8); } }

AES

AES加密算法是密碼學(xué)中的高級加密標(biāo)準(zhǔn),該加密算法采用對稱分組密碼體制,密鑰長度的最少支持為128、192、256,分組長度128位,算法應(yīng)易于各種硬件和軟件實現(xiàn)。這種加密算法是美國聯(lián)邦政府采用的區(qū)塊加密標(biāo)準(zhǔn),AES標(biāo)準(zhǔn)用來替代原先的DES,已經(jīng)被多方分析且廣為全世界所使用。JCE,Java Cryptography Extension,在早期JDK版本中,由于受美國的密碼出口條例約束,Java中涉及加解密功能的API被限制出口,所以Java中安全組件被分成了兩部分: 不含加密功能的JCA(Java Cryptography Architecture )和含加密功能的JCE(Java Cryptography Extension)。JCE的API都在javax.crypto包下,核心功能包括:加解密、密鑰生成(對稱)、MAC生成、密鑰協(xié)商。加解密功能由Cipher組件提供,其也是JCE中最核心的組件。在設(shè)置Cipher 類的時候有幾個注意點:

Cipher在使用時需以參數(shù)方式指定transformation

transformation的格式為algorithm/mode/padding,其中algorithm為必輸項,如: AES/DES/CBC/PKCS5Padding,具體有哪些可看下表

缺省的mode為ECB,缺省的padding為PKCS5Padding

在block算法與流加密模式組合時, 需在mode后面指定每次處理的bit數(shù), 如DES/CFB8/NoPadding, 如未指定則使用缺省值, SunJCE缺省值為64bits

Cipher有4種操作模式: ENCRYPT_MODE(加密), DECRYPT_MODE(解密), WRAP_MODE(導(dǎo)出Key), UNWRAP_MODE(導(dǎo)入Key),初始化時需指定某種操作模式

算法/模式/填充16字節(jié)加密后數(shù)據(jù)長度不滿16字節(jié)加密后長度

AES/CBC/NoPadding16不支持

AES/CBC/PKCS5Padding3216

AES/CBC/ISO10126Padding3216

AES/CFB/NoPadding16原始數(shù)據(jù)長度

AES/CFB/PKCS5Padding3216

AES/CFB/ISO10126Padding3216

AES/ECB/NoPadding16不支持

AES/ECB/PKCS5Padding3216

AES/ECB/ISO10126Padding3216

AES/OFB/NoPadding16原始數(shù)據(jù)長度

AES/OFB/PKCS5Padding3216

AES/OFB/ISO10126Padding3216

AES/PCBC/NoPadding16不支持

AES/PCBC/PKCS5Padding3216

AES/PCBC/ISO10126Padding3216

秘鑰的可以由我們自己定義,也可以是由AES自己生成,當(dāng)自己定義是需要是要注意:

根據(jù) AES 規(guī)范,可以是 16 字節(jié)、24 字節(jié)和32 字節(jié)長,分別對應(yīng) 128 位、192 位和 256 位;

為便于傳輸,一般對加密后的數(shù)據(jù)進(jìn)行 base64 編碼:

public static void main(String[] args) throws Exception { /* * 此處使用AES-128-ECB加密模式,key需要為16位。 */ String cKey = “1234567890123456”; // 需要加密的字串 String cSrc = “buxuewushu”; System.out.println(cSrc); // 加密 String enString = Encrypt(cSrc, cKey); System.out.println(“加密后的字串是:” + enString); // 解密 String DeString = Decrypt(enString, cKey); System.out.println(“解密后的字串是:” + DeString); } // 加密 public static String Encrypt(String sSrc, String sKey) throws Exception { if (sKey == null) { System.out.print(“Key為空null”); return null; } // 判斷Key是否為16位 if (sKey.length() != 16) { System.out.print(“Key長度不是16位”); return null; } byte[] raw = sKey.getBytes(“utf-8”); SecretKeySpec skeySpec = new SecretKeySpec(raw, “AES”); Cipher cipher = Cipher.getInstance(“AES/ECB/PKCS5Padding”);//“算法/模式/補(bǔ)碼方式” cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] encrypted = cipher.doFinal(sSrc.getBytes(“utf-8”)); return new Base64().encodeToString(encrypted);//此處使用BASE64做轉(zhuǎn)碼功能,同時能起到2次加密的作用。 } // 解密 public static String Decrypt(String sSrc, String sKey) throws Exception { try { // 判斷Key是否正確 if (sKey == null) { System.out.print(“Key為空null”); return null; } // 判斷Key是否為16位 if (sKey.length() != 16) { System.out.print(“Key長度不是16位”); return null; } byte[] raw = sKey.getBytes(“utf-8”); SecretKeySpec skeySpec = new SecretKeySpec(raw, “AES”); Cipher cipher = Cipher.getInstance(“AES/ECB/PKCS5Padding”); cipher.init(Cipher.DECRYPT_MODE, skeySpec); byte[] encrypted1 = new Base64().decode(sSrc);//先用base64解密 try { byte[] original = cipher.doFinal(encrypted1); String originalString = new String(original,“utf-8”); return originalString; } catch (Exception e) { System.out.println(e.toString()); return null; } } catch (Exception ex) { System.out.println(ex.toString()); return null; } }

非對稱加密算法

非對稱加密算法中加密和解密用的不是同一個秘鑰,所以叫作非對稱加密算法。在非對稱加密算法每個用戶都有兩把鑰匙,一把公鑰一把私鑰。公鑰是對外發(fā)布的,所有人都看的到所有人的公鑰,私鑰是自己保存,每個人都只知道自己的私鑰而不知道別人的。而也正是在非對稱加密算法中有加密和解密、加簽和驗簽的概念。接下來我們解釋一下這幾個概念是什么意思。

加密和解密

用該用戶的公鑰加密后只能該用戶的私鑰才能解密。這種情況下,公鑰是用來加密信息的,確保只有特定的人(用誰的公鑰就是誰)才能解密該信息。所以這種我們稱之為加密和解密。下面我拿A銀行和小明來舉例子吧。假設(shè)這2者之間是用不對稱的加密算法來保證信息傳輸?shù)陌踩裕ú槐坏谌酥佬畔⒌暮x及篡改信息)。大致流程如下:首先小明發(fā)了一條信息給A銀行“我要存500元”。

這條信息小明會根據(jù)A銀行的對外發(fā)布的公鑰把這條信息加密了,加密之后,變成“XXXXXXX”發(fā)給A銀行。中間被第三者截獲,由于沒有A銀行的私鑰無法解密,不能知道信息的含義,也無法按正確的方式篡改。

所以拿這條加密信息是沒辦法的。最后被A銀行接受,A銀行用自己的私鑰去解密這條信息,解密成功,讀取內(nèi)容,執(zhí)行操作。然后得知消息是小明發(fā)來的,便去拿小明的公鑰,把“操作成功(或失敗)”這條信息用小明的公鑰加密,發(fā)給小明。同理最后小明用自己的私鑰解開,得知知乎發(fā)來的信息內(nèi)容。其他人截獲因為沒有小明的私鑰所以也沒有用。

加簽和驗簽

還有第二種情況,公鑰是用來解密信息的,確保讓別人知道這條信息是真的由我發(fā)布的,是完整正確的。接收者由此可知這條信息確實來自于擁有私鑰的某人,這被稱作數(shù)字簽名,公鑰的形式就是數(shù)字證書。所以這種我們稱之為加簽和驗簽。繼續(xù)拿小明和銀行A舉例子。銀行A發(fā)布了一個銀行客戶端的補(bǔ)丁供所有用戶更新,那為了確保人家下載的是正確完整的客戶端,銀行A會為這個程序打上一個數(shù)字簽名(就是用銀行A的私鑰對這個程序加密然后發(fā)布)。

你需要在你的電腦里裝上銀行A的數(shù)字證書(就是銀行對外發(fā)布的公鑰),然后下載好這個程序,數(shù)字證書會去解密這個程序的數(shù)字簽名,解密成功,補(bǔ)丁得以使用。同時你能知道這個補(bǔ)丁確實是來自這個銀行A,是由他發(fā)布的,而不是其他人發(fā)布的。

實戰(zhàn)演練

我們在開發(fā)過程中經(jīng)常使用的非對稱加密算法就是RSA算法。接下來我們使用Java實現(xiàn)RSA算法。

生成密鑰

首先是生成key的部分,生成key有好多種做法,這里我介紹三種

命令行:可以使用openssl進(jìn)行生成公鑰和私鑰

-- 生成公鑰和私鑰

openssl genrsa -out key.pem 1024

-out 指定生成文件,此文件包含公鑰和私鑰兩部分,所以即可以加密,也可以解密

1024 生成密鑰的長度

使用網(wǎng)站:生成密鑰的網(wǎng)站

使用代碼:可以指定生成密鑰的長度,最低是512

public static KeyPair buildKeyPair() throws NoSuchAlgorithmException {

final int keySize = 2048;

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM);

keyPairGenerator.initialize(keySize);

return keyPairGenerator.genKeyPair();

}

加密

有了密鑰,就可以進(jìn)行加密的操作了,接下來就介紹關(guān)于RSA的加密操作,非常簡單只要傳進(jìn)來公鑰和需要加密的數(shù)據(jù)即可。

--- 加密 public static byte[] encrypt(PublicKey publicKey, String message) throws Exception { Cipher cipher = Cipher.getInstance(RSA_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(message.getBytes(UTF8)); }

解密

--- 解密 public static byte[] decrypt(PrivateKey privateKey, byte [] encrypted) throws Exception { Cipher cipher = Cipher.getInstance(RSA_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(encrypted); }

加簽

/** * 使用RSA簽名 */ private static String signWithRSA(String content, PrivateKey privateKey) throws Exception { Signature signature = Signature.getInstance(“SHA1WithRSA”); signature.initSign(privateKey); signature.update(content.getBytes(“utf-8”)); byte[] signed = signature.sign(); return base64Encode(signed); }

驗簽

/** * 使用RSA驗簽 */ private static boolean checkSignWithRSA(String content, PublicKey publicKey,String sign) throws Exception { Signature signature = Signature.getInstance(“SHA1WithRSA”); signature.initVerify(publicKey); signature.update(content.getBytes(“utf-8”)); return signature.verify(base64Decode(sign)); }在加簽驗簽的時候需要傳入一個數(shù)字簽名標(biāo)準(zhǔn),我們這里填的是SHA1WithRSA ,它的意思是用SHA算法進(jìn)行簽名,用RSA算法進(jìn)行加密。算法說明:在對進(jìn)行SHA1算法進(jìn)行摘要計算后,要求對計算出的摘要進(jìn)行處理,而不是直接進(jìn)行RSA算法進(jìn)行加密。要求把SHA1摘要的數(shù)據(jù)進(jìn)行壓縮到20個字節(jié)。在前面插入15個字節(jié)標(biāo)示數(shù)據(jù)。所以結(jié)構(gòu)如下

30(數(shù)據(jù)類型結(jié)構(gòu))21(總長度)30(數(shù)據(jù)類型)09(長度)06 05 2B 0E 03 02 1A 0500【數(shù)據(jù)具體類型不清楚-請專家指正】 04 (數(shù)據(jù)類型) 14 (長度) + SHA1簽名數(shù)據(jù)最后進(jìn)行RSA加密。所以我們填寫的XXXWithRSA,這個XXX代表的就是使用什么摘要算法進(jìn)行加簽,至于摘要算法是什么,隨后會有詳細(xì)的說明。調(diào)用實驗一下

public static void main(String[] args) throws Exception { KeyPair keyPair = buildKeyPair(); byte[] encryptData = encrypt(keyPair.getPublic(), “不學(xué)無數(shù)”); System.out.println(String.format(“加密后的數(shù)據(jù):%s”,base64Encode(encryptData))); System.out.println(String.format(“解密后的數(shù)據(jù):%s”,new String(decrypt(keyPair.getPrivate(),encryptData),UTF8))); String context = “加簽的字符串”; String sign = signWithRSA(context, keyPair.getPrivate()); System.out.println(String.format(“生成的簽名:%s”,sign)); Boolean checkSignWithRSA = checkSignWithRSA(context, keyPair.getPublic(), sign); System.out.println(String.format(“校驗的結(jié)果:%s”,checkSignWithRSA.toString())); }輸出為

加密后的數(shù)據(jù):Bi8b4eqEp+rNRhDaij8vVlNwKuICbPJfFmyzmEXKuAgEgzMPb8hAmYiGN+rbUKWeZYJKJd0fiOXv 6YrYqd7fdast/m443qQreRLxdQFScwvCvj9g1YnPzbU2Q/jIwqAPopTyPHNNngBmFki+R/6V4DYt HA5gniaUMYzynHdD+/W+x8ZYmwiuuS63+7wXqL36aLKe0H50wELOpSn45Gvni8u+5zPIoHV7PBiz trCnQvne5LxFKDprrS3td1/76qyupFd+Ul3hsd+gjbAyN2MlXcAFMrGVaRkopWwc9hP1BsPvS52q /8jOVdbeyU9BziVhViz1V0TtGW8bfbEnIStc3Q== 解密后的數(shù)據(jù):不學(xué)無數(shù) 生成的簽名:wvUXtr2UI0tUXmyMTTUBft8oc1dhvtXSBrFFetI5ZoxMm91TbXRWD31Pgqkg72ADxx9TEOAM3Bm1 kyzfBCZZpoq6Y9SM4+jdJ4sMTVtw0wACPglnPDAGs8sG7nnLhXWNQ1Y4pl4ziY6uLxF1TzQLFTxu NAS7nyljbG69wrb9R3Sv5t8r1I54rYCVGSVFmTrGf+dSCjxABZv6mH8nygVif7zN1vU1+nSDKcON Vtrpv0xCQHVBqnHPA6OiDm5GzBQxjD5aQt8mfgv8JJrB52TEa4JPYoC5Zw4JHlL++OvPwMpJgnuG yg5vnWhxE2ncTzM+/pZ+CnXF2Dqv/JMQOfX6tA== 校驗的結(jié)果:true

摘要算法

數(shù)據(jù)摘要算法是密碼學(xué)算法中非常重要的一個分支,它通過對所有數(shù)據(jù)提取指紋信息以實現(xiàn)數(shù)據(jù)簽名、數(shù)據(jù)完整性校驗等功能,由于其不可逆性,有時候會被用做敏感信息的加密。數(shù)據(jù)摘要算法也被稱為哈希(Hash)算法或散列算法。消息摘要算法的主要特征是加密過程不需要密鑰,并且經(jīng)過加密的數(shù)據(jù)無法被解密,只有輸入相同的明文數(shù)據(jù)經(jīng)過相同的消息摘要算法才能得到相同的密文。(摘要可以比方為指紋,消息摘要算法就是要得到文件的唯一職位)

特點

無論輸入的消息有多長,計算出來的消息摘要的長度總是固定的。一般地,只要輸入的消息不同,對其進(jìn)行摘要以后產(chǎn)生的摘要消息也必不相同;但相同的輸入必會產(chǎn)生相同的輸出。只能進(jìn)行正向的信息摘要,而無法從摘要中恢復(fù)出任何的消息,甚至根本就找不到任何與原信息相關(guān)的信息(不可逆性)。好的摘要算法,沒有人能從中找到“碰撞”或者說極度難找到,雖然“碰撞”是肯定存在的(碰撞即不同的內(nèi)容產(chǎn)生相同的摘要)。

應(yīng)用

一般地,把對一個信息的摘要稱為該消息的指紋或數(shù)字簽名。數(shù)字簽名是保證信息的完整性和不可否認(rèn)性的方法。數(shù)據(jù)的完整性是指信宿接收到的消息一定是信源發(fā)送的信息,而中間絕無任何更改;

信息的不可否認(rèn)性是指信源不能否認(rèn)曾經(jīng)發(fā)送過的信息。其實,通過數(shù)字簽名還能實現(xiàn)對信源的身份識別(認(rèn)證),即確定“信源”是否是信宿意定的通信伙伴。數(shù)字簽名應(yīng)該具有唯一性,即不同的消息的簽名是不一樣的;

同時還應(yīng)具有不可偽造性,即不可能找到另一個消息,使其簽名與已有的消息的簽名一樣;還應(yīng)具有不可逆性,即無法根據(jù)簽名還原被簽名的消息的任何信息。這些特征恰恰都是消息摘要算法的特征,所以消息摘要算法適合作為數(shù)字簽名算法。

有哪些具體的消息摘要算法?

CRC8、CRC16、CRC32:CRC(Cyclic Redundancy Check,循環(huán)冗余校驗)算法出現(xiàn)時間較長,應(yīng)用也十分廣泛,尤其是通訊領(lǐng)域,現(xiàn)在應(yīng)用最多的就是 CRC32 算法,它產(chǎn)生一個4字節(jié)(32位)的校驗值,一般是以8位十六進(jìn)制數(shù),如FA 12 CD 45等。CRC算法的優(yōu)點在于簡便、速度快,嚴(yán)格的來說,CRC更應(yīng)該被稱為數(shù)據(jù)校驗算法,但其功能與數(shù)據(jù)摘要算法類似,因此也作為測試的可選算法。

MD2 、MD4、MD5:這是應(yīng)用非常廣泛的一個算法家族,尤其是 MD5(Message-Digest Algorithm 5,消息摘要算法版本5),它由MD2、MD3、MD4發(fā)展而來,由Ron Rivest(RSA公司)在1992年提出,目前被廣泛應(yīng)用于數(shù)據(jù)完整性校驗、數(shù)據(jù)(消息)摘要、數(shù)據(jù)加密等。

MD2、MD4、MD5 都產(chǎn)生16字節(jié)(128位)的校驗值,一般用32位十六進(jìn)制數(shù)表示。MD2的算法較慢但相對安全,MD4速度很快,但安全性下降,MD5比MD4更安全、速度更快。

SHA1、SHA256、SHA384、SHA512:SHA(Secure Hash Algorithm)是由美國專門制定密碼算法的標(biāo)準(zhǔn)機(jī)構(gòu)——美國國家標(biāo)準(zhǔn)技術(shù)研究院(NIST)制定的,SHA系列算法的摘要長度分別為:

SHA為20字節(jié)(160位)、SHA256為32字節(jié)(256位)、 SHA384為48字節(jié)(384位)、SHA512為64字節(jié)(512位),由于它產(chǎn)生的數(shù)據(jù)摘要的長度更長,因此更難以發(fā)生碰撞,因此也更為安全,它是未來數(shù)據(jù)摘要算法的發(fā)展方向。由于SHA系列算法的數(shù)據(jù)摘要長度較長,因此其運(yùn)算速度與MD5相比,也相對較慢。

RIPEMD、PANAMA、TIGER、ADLER32 等:RIPEMD是Hans Dobbertin等3人在對MD4,MD5缺陷分析基礎(chǔ)上,于1996年提出來的,有4個標(biāo)準(zhǔn)128、160、256和320,其對應(yīng)輸出長度分別為16字節(jié)、20字節(jié)、32字節(jié)和40字節(jié)。TIGER由Ross在1995年提出。Tiger號稱是最快的Hash算法,專門為64位機(jī)器做了優(yōu)化。

實戰(zhàn)演練

在單獨的使用摘要算法時我們通常使用的MD5算法,所以我們這里就單獨說明使用Java實現(xiàn)MD5算法。

public static String getMD5Str(String str) throws Exception { try { // 生成一個MD5加密計算摘要 MessageDigest md = MessageDigest.getInstance(“MD5”); // 計算md5函數(shù) md.update(str.getBytes()); // digest()最后確定返回md5 hash值,返回值為8為字符串。因為md5 hash值是16位的hex值,實際上就是8位的字符 // BigInteger函數(shù)則將8位的字符串轉(zhuǎn)換成16位hex值,用字符串來表示;得到字符串形式的hash值 return new BigInteger(1, md .digest()).toString(16); } catch (Exception e) { throw new Exception(“MD5加密出現(xiàn)錯誤,”+e.toString()); } }

文章中涉及到的代碼地址:https://github.com/modouxiansheng/Doraemon

參考

https://zhuanlan.zhihu.com/p/20064358

https://time.geekbang.org/column/article/224701

https://my.oschina.net/OutOfMemory/blog/3131916

https://www.zz-news.com/com/zhongshanfengyu/news/itemid-674743.html

https://www.hbhncj.com/article-53-3443-1.html

https://www.zhihu.com/question/33645891

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4671

    瀏覽量

    67767
  • md5
    md5
    +關(guān)注

    關(guān)注

    0

    文章

    28

    瀏覽量

    20825
  • RSA
    RSA
    +關(guān)注

    關(guān)注

    0

    文章

    59

    瀏覽量

    18813
  • SHA
    SHA
    +關(guān)注

    關(guān)注

    0

    文章

    16

    瀏覽量

    8420

原文標(biāo)題:關(guān)于加解密、加簽驗簽的那些事

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    基于OM6626 NRF528210系列的ESL電子價應(yīng)用

    在競爭激烈的零售行業(yè),效率和顧客體驗至關(guān)重要。傳統(tǒng)的紙質(zhì)價簽在更新頻率、準(zhǔn)確性和管理成本上存在諸多不足。而電子價(ESL,Electronic Shelf Label)作為一種智能化解決方案,正在
    的頭像 發(fā)表于 07-30 15:11 ?198次閱讀
    基于OM6626 NRF528210系列的ESL電子價<b class='flag-5'>簽</b>應(yīng)用

    鴻蒙開發(fā):Universal Keystore Kit密鑰管理服務(wù) 簽名、介紹及算法規(guī)格

    為實現(xiàn)數(shù)據(jù)完整性保護(hù)和防抵賴,可使用生成/導(dǎo)入的密鑰,對數(shù)據(jù)進(jìn)行簽名操作。
    的頭像 發(fā)表于 07-10 09:29 ?139次閱讀
    鴻蒙開發(fā):Universal Keystore Kit密鑰管理服務(wù) 簽名、<b class='flag-5'>驗</b><b class='flag-5'>簽</b>介紹及算法規(guī)格

    中國化學(xué)會與華為合作協(xié)議

    中國化學(xué)會與華為合作協(xié)議 日前,中國化學(xué)會與華為簽署戰(zhàn)略合作協(xié)議,將在化學(xué)后備人才挖掘與培養(yǎng)、人才評價模式探索等方面開展合作。
    的頭像 發(fā)表于 04-03 11:52 ?654次閱讀

    鴻蒙OS開發(fā)問題:(ArkTS)【 RSA加解密,解決中文亂碼等現(xiàn)象】

    RSA加解密開始構(gòu)建工具類就是舉步維艱,官方文檔雖然很全,但是還是很多小瑕疵,在自己經(jīng)過幾天的時間,徹底解決了中文亂碼的問題、分段加密的問題。
    的頭像 發(fā)表于 03-27 21:23 ?1430次閱讀
    鴻蒙OS開發(fā)問題:(ArkTS)【 RSA<b class='flag-5'>加解密</b>,解決中文亂碼等現(xiàn)象】

    Ansys多物理場核解決方案獲得英特爾代工認(rèn)證

    Ansys的多物理場核解決方案已經(jīng)成功獲得英特爾代工(Intel Foundry)的認(rèn)證,這一認(rèn)證使得Ansys能夠支持對采用英特爾18A工藝技術(shù)設(shè)計的先進(jìn)集成電路(IC)進(jìn)行核驗證。18A工藝技術(shù)集成了新型RibbonFET晶體管技術(shù)和背面供電技術(shù),代表了半導(dǎo)體制造
    的頭像 發(fā)表于 03-11 11:25 ?548次閱讀

    電子價迭代:向多色顯示發(fā)展、無源方案升級

    場規(guī)模達(dá)到 669.8 億美元。巨大的市場成為電子價簽上游產(chǎn)業(yè)鏈廠商加速布局的動力。那么,電子價市場哪些發(fā)展趨勢,芯片廠商推出了哪些產(chǎn)品適配市場需求呢?
    的頭像 發(fā)表于 03-11 00:21 ?3494次閱讀
    電子價<b class='flag-5'>簽</b>迭代:向多色顯示發(fā)展、無源方案升級

    鴻蒙ArkUI開發(fā)-實現(xiàn)增刪Tab頁

    本文以瀏覽器中增加或刪除頁簽為例,實現(xiàn)Tabs中頁的增刪功能。
    的頭像 發(fā)表于 01-29 18:43 ?1432次閱讀
    鴻蒙ArkUI開發(fā)-實現(xiàn)增刪Tab頁<b class='flag-5'>簽</b>

    新思科技攜手臺積公司推出“從架構(gòu)探索到核” 統(tǒng)一設(shè)計平臺

    新思科技3DIC Compiler集成了3Dblox 2.0標(biāo)準(zhǔn),可用于異構(gòu)集成和“從架構(gòu)探索到核”的完整解決方案。
    的頭像 發(fā)表于 01-12 13:40 ?418次閱讀
    新思科技攜手臺積公司推出“從架構(gòu)探索到<b class='flag-5'>簽</b>核” 統(tǒng)一設(shè)計平臺

    基于FPGA的可編程AES加解密IP

    可編程AES加解密IP內(nèi)建密鑰擴(kuò)展功能,使用初始密鑰產(chǎn)生擴(kuò)展密鑰,用于加解密過程。可編程AES加解密IP處理128-bit分組數(shù)據(jù),并且支持可編程的密鑰長度:128-bit,192-bit和256-bit。
    發(fā)表于 01-09 10:49 ?361次閱讀
    基于FPGA的可編程AES<b class='flag-5'>加解密</b>IP

    紙質(zhì)標(biāo)簽已OUT?看電子價方案如何提升零售效率

    在零售業(yè)的日常運(yùn)營中,價格標(biāo)簽扮演著至關(guān)重要的角色。不過傳統(tǒng)的紙質(zhì)價格標(biāo)簽已經(jīng)逐漸不適應(yīng)現(xiàn)代市場的需求: 紙質(zhì)標(biāo)簽 更新速度慢、易出錯、維護(hù)成本高昂等問題帶來的經(jīng)營性價比在不斷降低。 智能電子價
    的頭像 發(fā)表于 12-28 08:44 ?369次閱讀
    紙質(zhì)標(biāo)簽已OUT?看電子價<b class='flag-5'>簽</b>方案如何提升零售效率

    eCryptfs整體架構(gòu)和核心加解密機(jī)制介紹

    的注冊函數(shù)。之后eCryptfs根據(jù)mountsession中保存的key signature參數(shù)從keyring中找到對應(yīng)密鑰(FEKEK),再調(diào)用crypto模塊API完成文件加解密。 eCryptfs核心加解密
    的頭像 發(fā)表于 11-29 11:43 ?622次閱讀
    eCryptfs整體架構(gòu)和核心<b class='flag-5'>加解密</b>機(jī)制介紹

    通過構(gòu)架來處理加解密需求

    SPE主要是提供需要安全保護(hù)的服務(wù),例如固件更新、加解密;而NSPE則是一般使用者執(zhí)行應(yīng)用程序的環(huán)境。 如果在NSPE中執(zhí)行的應(yīng)用程序使用到secure層級的服務(wù),則需要透過特定API來呼叫(這個
    的頭像 發(fā)表于 11-02 16:15 ?253次閱讀
    通過構(gòu)架來處理<b class='flag-5'>加解密</b>需求

    探秘STM32U5安全特性|硬件加解密引擎與軟件算法對比

    探秘STM32U5安全特性|硬件加解密引擎與軟件算法對比
    的頭像 發(fā)表于 10-27 10:23 ?1499次閱讀
    探秘STM32U5安全特性|硬件<b class='flag-5'>加解密</b>引擎與軟件算法對比

    基于FPGA的PCI硬件加解密卡的設(shè)計方案

    電子發(fā)燒友網(wǎng)站提供《基于FPGA的PCI硬件加解密卡的設(shè)計方案.pdf》資料免費下載
    發(fā)表于 10-18 11:18 ?1次下載
    基于FPGA的PCI硬件<b class='flag-5'>加解密</b>卡的設(shè)計方案

    介紹采用瑞薩RA2L1作為專用加解密協(xié)處理器的方案

    數(shù)據(jù)安全在當(dāng)今系統(tǒng)設(shè)計中變得越來越重要,當(dāng)今數(shù)據(jù)的加密和基本分為了本機(jī)和協(xié)處理兩個方式,本機(jī)是最常見也是最簡單的加密模式
    的頭像 發(fā)表于 10-10 14:40 ?459次閱讀
    介紹采用瑞薩RA2L1作為專用<b class='flag-5'>加解密</b>協(xié)處理器的方案