最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

JAVA密碼學功能實現(xiàn)大集合(2022.7.16更新)

2022-02-27 21:56 作者:寂風也過路  | 我要投稿

一、序章

近一個半月的抽空,約莫有四十個小時,查閱無數(shù)他人文檔,翻閱各種官方說明和標準文件,反復(fù)修改整理......我終于!終于寫好了這個使用示例類!

不得不說,這個方向上的示例代碼真的少,甚至一些庫里的類都沒有解釋方法含義,全靠硬啃源碼+參考前人使用示例+用OpenssL進行比對,這才能稍稍猜出答案。

當然,網(wǎng)上材料這么少,估計也是因為深度使用純軟代碼來實現(xiàn)PKI業(yè)務(wù)的概率較低,更多的時候其實還是輕度使用+用硬件安全設(shè)備(HSM),畢竟會更好一些。

不過保不齊就有用到的時候,所以我算是"未雨綢繆"(杞人憂天)?

反正就是提前將這些代碼研究了一通,整理了出來,以后要用就很方便了,而且也算是在填補空白(恬不知恥)。

下圖是我整理出的方法列表:

2022.2.27首稿具備的方法

二、已具備的方法介紹

注:本文內(nèi)容僅代表截止至2022.2.27的情況,后續(xù)有更新的話,未必會同步在本文進行更新

注:2022.7.8發(fā)現(xiàn),"OpenssL 1.1.1h 22 Sep 2020"版本生成的RSA密鑰對,在本示例的代碼中進行私鑰加載老是有問題。其他版本OpenssL(1.0.2、1.1.1i、3.0等實測過)未出現(xiàn)該問題。經(jīng)過分析后發(fā)現(xiàn),該版本產(chǎn)生的私鑰文件內(nèi)容經(jīng)過PEMParser加載后,是一個PEMKeyPair對象,而非常見的PrivateKeyInfo對象,于是加載成私鑰對象時,需要進行特殊處理,然后用于加解密就沒發(fā)現(xiàn)問題了。

注:個人能力有限,有些地方應(yīng)該有更好的寫法或者其他的寫法,無法全部想到,如果有大佬看到,還請不吝賜教

注:有些地方因為一開始構(gòu)思過于簡單,所以經(jīng)歷了反復(fù)的修改,所以測試可能會有遺漏,如有發(fā)現(xiàn),希望能夠指出,十分感謝!

注:因為代碼太長(1300+行),就不貼這里了,要看可以去github倉庫閱覽,還有單元測試的使用示范(300+行)。倉庫地址:https://github.com/17lhf/happyTest


1、獲取BC庫支持的密鑰算法

特別推薦閱覽一遍,這樣你在用字符串指定的時候,就知道庫里面有沒有支持了

2、生成摘要

支持MD5、SHA-1(或SHA1)、SHA-256(或SHA256)

3、生成密鑰對

可選算法:DiffieHellman(等同于:DH)、DSA、RSA

RSA時推薦長度為:2048/1024/3096,DH時推薦為:1024,DSA時推薦長度為:1024

其實我還有提取密鑰中含有的P、X、Q、G之類密碼學理論知識中的密鑰關(guān)鍵值,但是網(wǎng)上有好多大佬都有詳盡的講解了,我這里就不獻丑了......

4、生成ECC密鑰對

注意:密鑰長度推薦256

5、讀取RSA私鑰文件轉(zhuǎn)換成私鑰對象

注意:這個方法只支持PKCS1標準格式且無口令保護的私鑰

注意:方法使用了sun.*包,可能會導(dǎo)致打包失敗

6、從文件加載受口令保護的私鑰

注意:這個方法只支持PKCS8標準格式

注意:私鑰類型支持ECC、RSA

7、從文件加載無口令保護私鑰

注意:文件要求是PKCS8標準格式

注意:私鑰類型支持ECC、RSA

注意:2022.7.20新增對加載后是PEMKeyPair的特殊私鑰文件的支持

8、從文件中獲取PKCS8的無口令保護的私鑰,然后轉(zhuǎn)成以指定口令保護的PKCS8私鑰,并將結(jié)果存入文件

9、從文件加載公鑰

注意:密鑰類型支持ECC、RSA

10、從文件加載公鑰方式二

注意:密鑰類型支持ECC、RSA

11、輸出pem格式的密鑰內(nèi)容到控制臺

可選算法:DiffieHellman(等同于:DH)、DSA、RSA

RSA時推薦長度為:2048/1024/3096,DH時推薦為:1024,DSA時推薦長度為:1024

12、輸入pem格式的密鑰到指定文件中

可選算法:DiffieHellman(等同于:DH)、DSA、RSA

RSA時推薦長度為:2048/1024/3096 DH時推薦為:1024 DSA時推薦長度為:1024

13、生成證書請求

注意:密鑰類型支持ECC、RSA

14、生成附帶一些擴展字段的證書請求

注意:擴展字段方面主要是舉例說明,實際使用要做修改

注意:算法類型支持ECC、RSA

涵蓋擴展字段:

keyUsage(密鑰用途)

extendedKeyUsage(擴展密鑰用途)(可自定義擴展密鑰字段)

15、分步進行csr生成

環(huán)節(jié)1:利用公鑰和subject生成csr中待簽名的部分

環(huán)節(jié)2:將獲取到的被私鑰簽名后的簽名值與csr中待簽名的數(shù)據(jù)進行拼裝,生成csr

16、將csr對象存入pem格式的文件中

17、讀取證書請求文件,并加載成一個證書請求對象

注意:證書請求文件的編碼方式支持“PEM”,“DER”

18、從證書請求中獲取公鑰

注意:算法類型支持ECC、RSA

19、獲取證書請求中包含的一些信息

涵蓋:

公鑰算法標識

證書請求簽名值

擴展字段OID(ExtensionOIDs)

關(guān)鍵擴展字段OID(CriticalExtensionOIDs)

非關(guān)鍵擴展字段OID(NonCriticalExtensionOIDs)

CSR使用者Subject及各個屬性(Country、Province、State、local、Organization、Organization Unit、EmailAddress、?Common name)

20、頒發(fā)V1自簽名證書

21、頒發(fā)V3無擴展屬性證書

注意:僅支持RSA證書頒發(fā)

注意:Java頒發(fā)的子證書無法通過SSL或者OpenssL的證書鏈檢驗,有可能是頒發(fā)者的subject屬性順序錯了,具體修復(fù)這個bug可以看我的代碼里的描述,這是Java頒發(fā)子證書的一個坑。

22、頒發(fā)V3證書,同時設(shè)置一些擴展字段

注意:擴展字段方面主要是舉例說明,實際使用要做修改

注意:僅支持RSA證書頒發(fā)

注意:Java頒發(fā)的子證書無法通過SSL或者OpenssL的證書鏈檢驗,有可能是頒發(fā)者的subject屬性順序錯了,具體修復(fù)這個bug可以看我的代碼里的描述,這是Java頒發(fā)子證書的一個坑。

包含:

復(fù)用CSR中的擴展字段(如:keyUsage、extendedKeyUsage)

涵蓋擴展字段:

basicConstraints(基本約束)

keyUsage(密鑰用途)

extendedKeyUsage(擴展密鑰用途)

subjectKeyIdentifier(使用者密鑰標識)

authorityKeyIdentifier(頒發(fā)者密鑰標識)

23、將一個證書對象以PEM格式存入對應(yīng)路徑的文件中

24、從證書中讀取出公鑰(含加載pem格式證書)

25、讀取證書文件并加載成一個證書對象(復(fù)雜式寫法)

注意:方法使用了sun.*包,可能會導(dǎo)致打包失敗

注意:證書編碼類型支持“PEM"和”DER“

26、驗證子證書是否由父證書頒發(fā)

注意:這里其實只做了密鑰簽名驗證,未用sn之類的數(shù)據(jù)驗證

subject、sn(好像用得不頻繁)之類可以通過解析子證書和父證書信息來比較

27、從der格式轉(zhuǎn)換成pem格式

注意:為了方便傳遞,一般der格式內(nèi)容會轉(zhuǎn)為十六進制串在網(wǎng)絡(luò)中傳遞,所以這里入?yún)⒂檬M制字符串

涵蓋文件類型;

CSR(證書請求)

CERT(數(shù)字證書)

PRV_KEY(私鑰)

PUB_KEY(公鑰)

28、將傳進來的pem格式證書字符串轉(zhuǎn)為der格式(Hex-String)

注意:方法使用了sun.*包,可能會導(dǎo)致打包失敗

29、依據(jù)傳入的證書對象,獲取證書的所有信息

涵蓋:

證書版本

證書的序列號

證書的簽名算法

證書簽名值

頒發(fā)者Subject及各個屬性值(Country、Province、State、local、Organization、Organization Unit、EmailAddress、?Common name)

使用者Subject及各個屬性值(Country、Province、State、local、Organization、Organization Unit、EmailAddress、?Common name)

證書有效期

證書是否處于有效期

擴展字段涵蓋:

BasicConstraints(基本約束字段)

KeyUsage(密鑰用途)

ExtendedKeyUsage(擴展密鑰用途)

注意:

?RFC5280(4.1.2.8節(jié))說明:issuerUniquelID和subjectUniqueID僅當版本為 2 或 3 時,這些字段必須顯示。 如果版本為 1,則不得顯示這些字段。 證書中存在使用者和頒發(fā)者唯一標識符,以處理隨著時間的推移重用使用者和/或頒發(fā)者名稱的可能性。 此配置文件建議不要對不同的實體重復(fù)使用名稱,并且 Internet 證書不要使用唯一標識符。 符合此配置文件的 CA 不得生成具有唯一標識符的證書。 符合此配置文件的應(yīng)用程序應(yīng)該能夠分析包含唯一標識符的證書,但沒有與唯一標識符關(guān)聯(lián)的處理要求

30、密鑰加密

注意:如果是ECC,則只能用公鑰加密,不支持私鑰加密數(shù)據(jù)

支持的算法/模式/填充模式:

RSA(這么寫的話,模式和填充模式依賴于算法提供者怎么設(shè)置默認值,BC庫的話等同于“RSA/ECB/NoPadding”)

RSA/ECB/PKCS1Padding

RSA/ECB/OAEPWithSHA-1AndMGF1Padding

RSA/ECB/OAEPWithSHA-256AndMGF1Padding

ECIES (ECIES表示ECC)

31、解密

注意:如果是ECC,則只能用私鑰解密,不支持公鑰解密數(shù)據(jù)

注意:填寫的算法/模式/填充模式要與加密時使用的一致,否則將導(dǎo)致解密數(shù)據(jù)錯誤

支持的算法/模式/填充模式:

RSA(這么寫的話,模式和填充模式依賴于算法提供者怎么設(shè)置默認值,BC庫的話等同于“RSA/ECB/NoPadding”)

RSA/ECB/PKCS1Padding

RSA/ECB/OAEPWithSHA-1AndMGF1Padding

RSA/ECB/OAEPWithSHA-256AndMGF1Padding

ECIES?(ECIES表示ECC)

32、利用私鑰對數(shù)據(jù)進行簽名

注意:密鑰的算法支持:RSA,DSA,ECDSA、ECNR

注意:簽名過程中要用到的摘要算法,支持:SHA1,SHA256 (較常用的是SHA256)

33、分理論步驟進行利用私鑰對數(shù)據(jù)進行簽名

注意:中間使用經(jīng)驗得來的標準化方式,慎用!??!

注意:密鑰的算法支持:RSA,DSA

注意:簽名過程中要用到的摘要算法支持:SHA-1(或SHA1),SHA-256(或SHA256) (較常用的是SHA-256)

34、利用密鑰對數(shù)據(jù)進行驗簽

注意:密鑰的算法支持:RSA,DSA,ECDSA、ECNR

注意:簽名過程中用到的摘要算法,支持:SHA1,SHA256 (較常用的是SHA256)

注意:驗簽的時候,用到的算法都要與簽名時用到的算法一致,否則最后肯定時驗簽失敗

35、生成p12文件到指定文件夾中

注意:可選擇是否要放入證書鏈

注意:這種方式生成的p12文件等同于在openssl1.1.1版本中生成的p12文件

注意:在openssl3.0處進行解析驗證時,會出現(xiàn)無法正常顯示證書的問題。因為使用的加密方式是比較舊的RC2-40-CBC,該加密方式已被認為是不安全的,于是openssl在3.0中進行了剔除,3.0之前版本的openssl可以照常解析。

36、從文件中加載p12,并試著解析并獲取其中的數(shù)據(jù)

包含提?。核借€、證書、證書鏈

37、DER格式數(shù)據(jù)轉(zhuǎn)對象(2022.5.10新增)

支持:證書、證書請求、公鑰、私鑰

38、PEM格式數(shù)據(jù)轉(zhuǎn)對象(2022.5.10新增)

支持:證書、證書請求、公鑰、私鑰

39、利用RSA私鑰加載公鑰(2022.7.15新增)

僅支持RSA2048/1024長度

實測發(fā)現(xiàn):java生成密鑰對,則1024和2048長度的公鑰的指數(shù)都是用的65537(十進制)

40、RSA密鑰的分段加密(2022.7.16新增)

Java 默認的 RSA加密實現(xiàn)不允許明文長度超過密鑰長度減去 11(單位是字節(jié),也就是 byte)。
也就是說,如果我們定義的密鑰(如:java.security.KeyPairGenerator.initialize(int keySize) 來定義密鑰長度)長度為 1024(單位是位,也就是 bit),則生成的密鑰長度就是 1024位 /(8位/字節(jié)) = 128字節(jié),那么我們需要加密的明文長度不能超過 128字節(jié) -11 字節(jié) = 117字節(jié)
也就是說,我們最大能將 117 字節(jié)長度的明文進行加密,否則會出問題(拋諸如 javax.crypto.IllegalBlockSizeException: Data must not be longer than 11 bytes 的異常)

實測“RSA/ECB/PKCS1Padding”時,2048RSA還是最大245


BC庫的話,是密鑰長度減去1, 如127(128-1),255(256-1)。超過的話,報錯:org.bouncycastle.crypto.DataLengthException: input too large for RSA cipher.

但是,上面BC庫時所說的,都是NoPadding的情況,如果有Padding,則blockSize大小就不一樣了


另外,每次加密生成密文的長度等于密鑰長度,如1024bit的密鑰,加密一次出來的密文長度是256字節(jié)(byte)
所以分段加密的最終的密文長度,必然是密鑰長度的正整數(shù)倍(如:256字節(jié)、512字節(jié))

41、RSA密鑰的分段解密(2022.7.16新增)

解密分塊的大小,如果密鑰大小是2048則塊大小是256,如果是1024則最大的塊是128
此處的256和128其實對應(yīng)的就是加密時每段被加密后的密文的大小
如果是用BC庫,若輸入的size不是解密分塊大?。ǖ『媚鼙幻芪恼?,則不會報錯,但是解密結(jié)果與原文對不上
如果是用JAVA庫,若輸入的size不是解密分塊大?。ǖ『媚鼙幻芪恼?,則doFinal會報錯javax.crypto.BadPaddingException: Decryption error

三、補充說明

1、對比OpenssL食用更佳

OpenssL命令行實例

2、關(guān)于驗證密鑰匹配

驗證一個公鑰和一個私鑰是否匹配,其實就是加密一個數(shù)據(jù),然后解密,看看解密后的結(jié)果與原始數(shù)據(jù)是否一致(目前沒有找到更便捷的流程)
驗證一個私鑰與一本證書是否匹配,其實就是先從證書中提取公鑰,然后就是和上一個一樣的流程(目前沒有找到更便捷的流程)

3、遇到的一些報錯

3.1 java.security.InvalidKeyException:?IOException?:?Detect?premature?EOF?

發(fā)生場景:提供der格式數(shù)據(jù)來加載key對象,加載時報錯
原因:密鑰的數(shù)據(jù)不足,存在缺漏,導(dǎo)致解析失敗

四、最后

如果我的代碼對你有幫助,還請多多評論 點贊 收藏 轉(zhuǎn)發(fā)!

謝謝每個閱讀到這里的人!


JAVA密碼學功能實現(xiàn)大集合(2022.7.16更新)的評論 (共 條)

分享到微博請遵守國家法律
时尚| 建水县| 南雄市| 肇庆市| 绥阳县| 广南县| 曲靖市| 海宁市| 南溪县| 南澳县| 鸡泽县| 泾阳县| 永兴县| 清流县| 郴州市| 建德市| 汝城县| 阜康市| 兰坪| 灵丘县| 都匀市| 阜平县| 玉田县| 余庆县| 麦盖提县| 舟曲县| 蒲城县| 上饶县| 沛县| 彩票| 义马市| 玛纳斯县| 东丽区| 扶沟县| 景泰县| 武定县| 乌拉特后旗| 吴川市| 湘潭市| 西吉县| 江陵县|