有很多朋友向我詢問昨天我司發生的事情,對於此事小灰也感到很震驚。在事情真相查清楚之前,希望大家能夠理性看待。當然,如果真相確實爆料內容所說,也絕對不容姑息。
Java的加密知識也是Java常見的領域之一,加密技術的底層確實很複雜,運用了大量的數學知識,要弄明白非常複雜。但是Java語言中運用密碼加密工具卻是非常簡單。我們在Java裡面運用這些加密技術,只需要把原理和使用場景等搞明白就可以了,具體底層實現不用研究。
常用的加密算法有對稱加密算法,非對稱加密算法,哈希算法,數字籤名等幾類。
對稱加密顧名思義就是加密和解密是對稱的,加密時用一個秘鑰去加密,解密時用同一個秘鑰去解密,由信息發送方和接收方共同約定一個秘鑰。缺點是風險都在這個秘鑰上面,一旦被竊取,信息會暴露。所以安全級別不夠高。常用對稱加密算法有DES,3DES,AES等。在jdk中也都有封裝。
非對稱加密,顧名思義就是加密與解密的過程不是對稱的,不是用的同一個秘鑰。非對稱加密有個公私鑰對的概念,也就是有兩把秘鑰,一把是公鑰,一把是私鑰,一對公私鑰有固定的生成方法,在加密的時候,用公鑰去加密,接收方再用對應的私鑰去解密。使用時可以由接收方生成公私鑰對,然後將公鑰傳給加密方,這樣私鑰不會在網絡中傳輸,沒有被竊取的風險。比如github底層的ssh協議就是公私鑰非對稱加密。並且公鑰是可以由私鑰推導出來的,反過來卻不行,由通過公鑰無法推導出私鑰。常用算法有RSA,ECC等。ECC也是比特幣底層用的比較多的算法。通過和對稱加密的對比,可以看到,非對稱加密解決了秘鑰傳輸中的安全問題。
哈希算法,簡單說就是將任意數據都轉換成一個固定長度的字符串。通過哈希後的值幾乎無法推導出原文。而且兩個不同的原文哈希後結果一定不同。常用算法有MD5,SHA256等等。常用場景,md5常用場景是資料庫的密碼存儲。sha256在挖礦中可以用到。
非對稱加密也有一個問題,就是內容在發送前可能被篡改,因為公鑰是有可能被竊取的,所以竊取者完全可以改為發送別的內容。
解決的辦法就是數字籤名。數字籤名和非對稱加密是反過來的,也是有公私鑰對,但是是用私鑰籤名,用公鑰去驗證籤名。比如發送方除了發送用公鑰加密後的密文,還要發送籤名,籤名內容通常是密文哈希後的字符串,接收方首先驗證籤名是否正確,如果正確那麼密文解密後就是真正需要並且沒有被篡改過的內容。注意,籤名和非對稱用的是兩對不同的公私鑰。
上面是對幾個加密算法的一個簡單講解,除了上面的還有base58等,比特幣底層安全也是依賴於加密。後面會一個一個介紹要用到的加密算法的介紹和使用,但是僅僅是使用,底層不會講。
MD5MD5即Message-Digest Algorithm 5(信息-摘要算法5),用於確保信息傳輸完整一致。是計算機廣泛使用的雜湊算法之一(又譯摘要算法、哈希算法),主流程式語言普遍已有MD5實現。將數據(如漢字)運算為另一固定長度值,是雜湊算法的基礎原理,MD5的前身有MD2、MD3和MD4。
MD5算法具有以下特點:
1、壓縮性:任意長度的數據,算出的MD5值長度都是固定的。
2、容易計算:從原數據計算出MD5值很容易。
3、抗修改性:對原數據進行任何改動,哪怕只修改1個字節,所得到的MD5值都有很大區別。
4、強抗碰撞:已知原數據和其MD5值,想找到一個具有相同MD5值的數據(即偽造數據)是非常困難的。
MD5的作用是讓大容量信息在用數字籤名軟體籤署私人密鑰前被"壓縮"成一種保密的格式(就是把一個任意長度的字節串變換成一定長的十六進位數字串)。除了MD5以外,其中比較有名的還有sha-1、RIPEMD以及Haval等。
JDK就自帶了md5加密算法,直接調用很方便。需要引入一個類:
import java.security.MessageDigest;
首先創建一個springboot項目,加上一個web以來,內容如下:
SHA256學Java的對哈希算法都不陌生,畢竟每個類都有hashCode方法。
散列算法(Hash Algorithm),又稱哈希算法,雜湊算法,是一種從任意文件中創造小的數字「指紋」的方法。與指紋一樣,散列算法就是一種以較短的信息來保證文件唯一性的標誌,這種標誌與文件的每一個字節都相關,而且難以找到逆向規律。因此,當原有文件發生改變時,其標誌值也會發生改變,從而告訴文件使用者當前的文件已經不是你所需求的文件。
一個優秀的 hash 算法,將能實現:
正向快速:給定明文和 hash 算法,在有限時間和有限資源內能計算出 hash 值。
逆向困難:給定(若干) hash 值,在有限時間內很難(基本不可能)逆推出明文。
輸入敏感:原始輸入信息修改一點信息,產生的 hash 值看起來應該都有很大不同。
衝突避免:很難找到兩段內容不同的明文,使得它們的 hash 值一致(發生衝突)。即對於任意兩個不同的數據塊,其hash值相同的可能性極小;對於一個給定的數據塊,找到和它hash值相同的數據塊極為困難。
但在不同的使用場景中,如數據結構和安全領域裡,其中對某一些特點會有所側重。
安全散列算法(英語:Secure Hash Algorithm,縮寫為SHA)是一個密碼散列函數家族,是FIPS所認證的安全散列算法。能計算出一個數字消息所對應到的,長度固定的字符串(又稱消息摘要)的算法。且若輸入的消息不同,它們對應到不同字符串的機率很高。
SHA家族的五個算法,分別是SHA-1、SHA-224、SHA-256、SHA-384,和SHA-512。主要適用於數字籤名標準(DigitalSignature Standard DSS)裡面定義的數字籤名算法(Digital Signature Algorithm DSA)。比特幣裡面的就是SHA-256算法。
說簡單一些,就是對一個對象的多個關鍵不重複信息組合起來,通過算法生成一個加密字符串。
繼續上一個項目,在對應的包下建一個工具類:
package btcdemo.btcdemo.security;
public class Sha256Utils
引入的加密類和md5一樣:
import java.security.MessageDigest;
下面是算法的具體內容:
下面是算法的測試類內容:
運行可以看到如下結果:
目前目錄結構如下:
項目代碼:https://github.com/guoyb1990/btc-demo.git
BASE64&BASE58Base64是網絡上最常見的用於傳輸8Bit字節碼的編碼方式之一,Base64就是一種基於64個可列印字符來表示二進位數據的方法。可查看RFC2045~RFC2049,上面有MIME的詳細規範。
Base64編碼是從二進位到字符的過程,可用於在HTTP環境下傳遞較長的標識信息。例如,在Java Persistence系統Hibernate中,就採用了Base64來將一個較長的唯一標識符(一般為128-bit的UUID)編碼為一個字符串,用作HTTP表單和HTTP GET URL中的參數。在其他應用程式中,也常常需要把二進位數據編碼為適合放在URL(包括隱藏表單域)中的形式。此時,採用Base64編碼具有不可讀性,需要解碼後才能閱讀。
Base64編碼要求把3個8位字節(3*8=24)轉化為4個6位的字節(4*6=24),之後在6位的前面補兩個0,形成8位一個字節的形式。 如果剩下的字符不足3個字節,則用0填充,輸出字符使用『=』,因此編碼後輸出的文本末尾可能會出現1或2個『=』。
jdk的工具包中就自帶base64的工具類,使用base64的方法也非常簡單,先新建一個工具類:
base64是可逆的,加密解密內容如下:
可以看到使用非常簡單,下面是測試類內容:
執行測試方法,結果如下:
可以看到base64非常簡單。
base58和base64一樣是一種二進位轉可視字符串的算法,主要用來轉換大整數值。區別是,轉換出來的字符串,去除了幾個看起來會產生歧義的字符,如 0 (零), O (大寫字母O), I (大寫的字母i) and l (小寫的字母L) ,和幾個影響雙擊選擇的字符,如/, +。結果字符集正好58個字符(包括9個數字,24個大寫字母,25個小寫字母)。不同的應用實現中,base58 最後查詢的字母表可能不同,所以沒有具體的標準。
可以看出,base58是base64的一種人性化的版本,是站在使用者的角度考慮的。
新建一個Base58的工具類,目錄結構如下:
工具類的大概內容結構如下:
因為內容過多,可以通過下載源碼查看。
下面是測試代碼:
運行結果如下:
可以看到,base58的使用方法是一樣的。
項目代碼:https://github.com/guoyb1990/btc-demo.git
—————END—————
喜歡本文的朋友們,歡迎長按下圖關注訂閱號程式設計師小灰,收看更多精彩內容