- 非對稱加密算法也稱為公開密鑰算法,其解決了對稱加密算法密鑰需要預分配的難題,使得現代密碼學的研究和應用取得了重大發展。
- 非對稱加密算法的基本特點如下:
- 加密密鑰和解密密鑰不相同;
- 密鑰對中的一個密鑰可以公開(稱為公開密鑰);
- 根據公開密鑰很難推算出私人密鑰。
- 根據非對稱加密算法的這些特點,我們可以使用非對稱加密算法進行數字簽名、密鑰交換及數據加密等。但是,由于非對稱加密算法的加密速度相對于對稱加密算法來說慢很多,所以一般不直接用于大量數據的加密,而是用于數據加密密鑰的交換和數字簽名。并非所有非對稱加密算法都可以同時用于密鑰交換和數字簽名,根據特點不一樣,有的只能用于密鑰交換,有的只能用于數字簽名,而有的可能兩者都可以。
- 數字簽名和密鑰交換對公開密鑰算法的要求有一定的區別,主要有如下兩點。
- 密鑰交換算法使用公開密鑰進行加密,使用私人密鑰進行解密;而數字簽名算法則使用私人密鑰進行加密,使用公開密鑰進行解密。
- 密鑰交換算法要求從加密密鑰(公開密鑰)很難推算出解密密鑰(私人密鑰);而數字簽名算法則要求從解密密鑰(公開密鑰)很難推算出加密密鑰(私人密鑰)。
- 目前來說,常用的非對稱加密算法有RSA、DH和DSA三種。其中RSA既可以用于密鑰交換,也可以用于數字簽名,因為它能夠同時滿足上述兩種不同的要求。DH算法一般來說只能用于密鑰交換,而DSA算法則是專用于數字簽名的算法。
- OpenSSL對于上述三種方法都支持,在指令里面也提供了相當豐富的應用,這些應用包括DH密鑰參數的生成和解析,DSA密鑰參數的生成和解析,DSA密鑰生成,RSA密鑰生成和使用RSA密鑰進行加密和解密。
- 如表所示 是目前OpenSSL支持的非對稱加密算法指令。?
RSA
- 同時具備簽名和密鑰交換特性的公開密鑰算法
- RSA加密的特點是輸入數據不可以超過RSA密鑰的長度(利用不同的補齊方式能夠加密的長度不一樣),輸出數據的長度和RSA密鑰長度相同,數據量很大的需要預先分隔
- 但是解密的時候輸入的密文數據需要和密鑰長度相等,如果密文長度很大,對每一塊分別進行解密,再將所有的數據鏈接起來可以得到明文
- 簽名的時候,先使用信息摘要函數比如(MD5,SHA1)生成160位或者128位文件的摘要信息,再使用RSA算法對摘要信息進行加密完成文件的數字簽名過程
- 驗簽的時候,使用相同的摘要算法生成文件的摘要信息 和 使用RSA公鑰解密得到的簽名方的摘要信息 進行比對
- Openssl案例:rsautl 和 dgst?
genrsa 指令格式
- 生成RSA密鑰
- 參數 -f4 和 -3 得出 genrsa可以生成基于不同指數的RSA密鑰,并可以使用不同的對稱密鑰對輸出的密鑰進行保護
- 還可以使用第三方加密軟件 加密硬件設備替代OpenSSL原本的庫生成RSA密鑰
輸出文件選項 out
- out指定密鑰輸出的文件名,輸出的是RSA私鑰,OpenSSL輸出的RSA私鑰會包含公鑰的模數n和指數e,在需要使用公鑰的時候需要從私鑰中讀取模數n和指數e,并進行格式的轉換
- 雖然RSA密鑰是成對的,包含私鑰和公鑰。其中公鑰包含了模數n和指數e,私鑰包含了d。
- ?OpenSSL輸出的文件名和后綴并沒有特殊的含義,可以取任意的名字
口令輸入選項 passout
- 輸入密鑰文件的加密口令,和Openssl通用口令輸入的格式是相同的,輸入源可以為指令輸入、文件、提示輸入、環境變量等等
- 如果使用的時候沒有輸入加密口令但是指定了需要使用加密算法的選項,程序會會在指令行界面提示輸入加密口令
- 如果不需要加密就可以忽略 加密口令
- 除非是測試,否則輸入的加密口令一定要足夠復雜、程度越長越好
加密算法的類型選項 des 3des idea aes128 aes192 aes256
- 使用對稱加密算法保護RSA私鑰
- 算法的類型:des 3des idea aes128 aes192 aes256
- 加密的模式都是 CBC
- 加密的密鑰和初始向量都是從提供的口令中提取出來的
指數參數 f4 和 3
- RSA算法的指數e 是公開的參數,屬于公鑰參數中的一部分,常用的數值有 3、17、65537
- OpenSSL支持 3 和 65537
- 很多硬件設備僅僅支持 65537
- 如果使用65537作為指數數值,就可以使用或省略 f4,因為默認是65537;使用-3選項會指定指數數值為3,二者不可以同時使用
密鑰的長度選項 numbits
- 密鑰長度影響加密的強度 ,強度與長度成正比,與加密時間成正比
- 原則:密鑰的使用周期越長 密鑰要求的長度越長
其他選項
- 使用engine指定第三方軟件加密庫或者硬件加密設備
- 目前常常使用硬件設備來生成和存放RSA密鑰,比如smart card、USBKey、加密機等硬件設備,他們具備自己的算法處理芯片,具備RSA算法的加密、解密、簽名和驗證等功能,使得RSA私鑰永遠不需要導出硬件設備就可以正常使用,其安全性要高于存儲在計算機磁盤
- engine選項后面是engine ID,這個ID是編寫engine接口的時候提供的,一般是一個描述性的字符串,只有正確加載engine設備和對應的驅動程序才可以正確使用
- 使用engine -t 測試目前有效的engine設備并獲取對應的ID名稱
- 隨機數文件選項rand提供產生隨機數的參考種子文件,可以進一步增加生成RSA密鑰的隨機性,增加安全性
- 如果沒有指定,程序會從標準輸出設備的狀態讀取信息作為隨機數的種子,隨機數文件可以為任意類型的文件
- 也可以調用engine設備的隨機數產生函數
應用實例
管理RSA密鑰
RSA指令格式
- 具體使用的時候需要對密鑰進行一些處理,比如重新設置加密口令或者對稱加密方法、解析私鑰輸出公鑰參數、格式轉換
- 使用rsa指令完成密鑰管理的功能
- * 密鑰學常用的密鑰管理涉及的是安全存放和安全傳輸 和這里的密鑰管理還存在很大的差異
- RSA還可以通過engine處理存儲在硬件設備中的私鑰
密鑰的格式轉換 inform和outform
- ?早期的Openssl只提供了REM、DER和NET三種類型
- 如果輸入的是RSA私鑰,支持的格式包括DER編碼格式、PEM編碼格式、PKCS#12編碼格式、Netscape編碼格式、舊版的IISSGC編碼格式及ENGINE格式。如果輸入的是RSA公鑰,則比RSA私鑰少支持一種PKCS#12格式,這是因為PKCS#12格式一般用來封裝證書和私鑰,而不直接用于封裝公鑰。
- 表格所示 是0.9.7版本支持的密鑰格式,最新的需要參考官網
- 指令字符串參數是只在inform或outform選項后面填寫的參數,它們一般對大小寫不敏感,比如對于DER編碼,可以指定為“-inform D”或者“-inform d”,它們是相同的。
- 如果指定密鑰的輸入格式為ENGINE,那么密鑰輸入文件(in選項指定的文件)的內容及其含義依具體的Engine接口代碼而定,可能是一個ID值,也可能是一個公鑰文件,甚至可能毫無意義。
- rsa指令支持的密鑰輸出格式(outform選項指定)比較少,僅包含DER編碼格式、PEM編碼格式、NET編碼格式及SGC編碼格式。其中,SGC編碼格式的指定需要使用-sgckey選項。
?輸入和輸出文件選項in和out
- in 指定了輸入密鑰的文件的名稱,默認情況下是RSA私鑰文件
- 如果參數指定了 -pubin 即輸入文件是包含了RSA的公鑰的文件
- 文件的具體格式可以使用-inform選項指定,如果在inform選項中指定輸入的文件格式是ENGINE格式并且使用了engine選項,那么輸入文件的內容和意義視具體的Engine接口代碼而定。
- out指定了輸出的文件的名稱,默認情況輸出的是RSA私鑰,但是使用了-pubout選項或者輸入為公鑰,輸出內容是RSA的公鑰
- 使用noout選項,本選項會被簡單的忽略掉
輸入和輸出口令選項 passin 和 passout
- 加密保護使用的口令包含加密保護使用的密鑰和初始向量,因此使用RSA的時候也需要輸入對應的口令
- passin選型指定了獲取RSA私鑰解密口令的源;passout選項指定了輸出RSA私鑰時進行加密的口令的源
- 如果輸入和輸出的是公鑰,那么passout選項會被簡單的忽略
- 如果輸入的密鑰文件需要口令進行解密而沒有使用pasin選項提供口令,那么程序會在指令行提示用戶輸入解密口令。
加密算法選項
- 跟genrsa指令一樣,rsa指令也提供了六種常用的分組加密算法用于加密RSA私鑰,這些算法包括DES、DES3、IDEA、128位AES、192位AES和256位AES算法。如果輸入使用了這些加密選項之一但是卻沒有使用pasout提供加密口令,那么將會在指令行提示輸入加密口令。
- 如果輸入的是公鑰或者輸出的是公鑰文件,那么該加密選項將會被忽略。
- 如果使用engine選項指定了有效的Engine設備,而Engine設備正好支持選定的加密算法,那么將采用Engine設備提供的加密算法加密生成密鑰,而不再是使用OpenSSL算法庫進行密鑰的加密。
信息輸出選項 text、noout、modules
- 使用text選項將會以明文的形式輸出密鑰各個參數的值
- 使用modulus選項則專門輸出模數值
- 如果使用了noout選項,那么就不會輸出任何密鑰到文件中,即便使用了out選項指定了輸出文件也會被忽略。
密鑰輸入和輸出的類型的選項 pubin和pubout
- 默認情況下輸入文件應該是RSA私鑰文件
- 如果要輸入的是RSA公鑰文件,則應該使用-pubin選項,該選項沒有參數
- 如果輸入的是RSA私鑰想得到一個與之對應的公鑰,需要指定pubout;任何和密鑰加密相關的選項都不會忽略,比如passout、des等。因為公鑰是公開的,不能泄密,也不需要對其進行保護
使用第三方加密庫或者硬件密鑰
- 使用engine選項指定要使用的第三方加密庫或者硬件。engine選項后面的參數是Engine的ID,通常是一個簡短的描述字符串,由相應的Engine接口代碼決定。
- 使用Engine選項后,rsa指令中兩個部分可能受到影響。首先是輸入密鑰,如果在inform中也指定了輸入密鑰格式是ENGINE格式,那么指令將試圖從Engine設備中加載密鑰而不是直接從文件中讀取密鑰,當然,這時候in選項提供的文件可能包含了一些加載密鑰需要的有用信息,也可能是Engine設備里面RSA私鑰對應的公鑰參數。其次,如果選定的密鑰加密算法在Engine中支持,那么將會使用Engine中的密鑰加密算法加密密鑰,而不再是使用OpenSSL默認的算法庫加密RSA私鑰。
其他選項
- check選項使用后,指令將會檢測輸入RSA密鑰的正確性和一致性。如果輸入或者輸出的密鑰是SGC格式,那么應該使用sgckey選項進行格式的轉換和調整。
- SGC選項目前一般不使用,它是一種經過修改的NET格式,用于舊版本的IS服務器
例子
?使用RSA密鑰
rsautl指令格式
- 由于rsautl指令的簽名功能沒有使用信息摘要算法,所以不能用來實現對文件或者其他大量的數據體進行真正意義上的數字簽名,而只能對符合表的輸入數據長度條件的小量數據進行數字簽名操作,也就是RSA私鑰加密操作。
- OpenSSL的rsautl指令的格式如下:
數據輸入和輸出文件選項in和out
- in選項指定了存儲輸入數據的文件選項,需要注意的是,如果執行的是加密操作(sign或者encrypt),那么輸入數據的長度一定要符合輸入數據長度的要求,否則rsautl指令將不能成功執行。
- 如果是解密操作(verify或者decrypt),那么輸入數據長度總是跟RSA密鑰長度相同。
- out選項指定了接收輸出數據的文件選項,對于rsautl指令來說,如果是加密操作(sign或者encrypt),那么輸出數據長度總是跟密鑰長度相同,比如對于1024位的RSA密鑰,輸出數據長度就總是128字節(1024位)。
- 默認的輸入輸出設備是標準輸入和輸出設備。?
操作類型選項sign、verify、encrypt和decrypt
- rsautl指令通過inkey選項指定加密或解密操作中要使用的密鑰的存儲文件。默認情況下,無論是上述四種操作中的哪一種,輸入的密鑰都應該為PEM格式的RSA私鑰。實際上,因為OpenSSL的PEM編碼,RSA私鑰里面包含了公鑰參數,所以即便在執行公鑰加密或者解密操作時輸入的是RSA私鑰,那么也能夠正確執行,因為指令程序會自動使用RSA私鑰里面的公鑰參數進行相應的公鑰操作。
- RSA密鑰的輸入格式可以是多樣的,默認的是PEM編碼格式,其具體的格式可以通過keyform選項來指定,keyform選項支持的參數可以上表。目前來說,如果輸入的是RSA私鑰,rsautl指令支持的格式包括DER編碼格式、PEM編碼格式、PKCS#12編碼格式、Netscape編碼格式、舊版的IISSGC編碼格式及ENGINE密鑰格式。如果輸入的是RSA公鑰,則比RSA私鑰少支持一種PKCS#12格式。如果keyform指定輸入的密鑰是ENGINE格式(-keyfrome),那么inkey指定的密鑰文件內容及意義要根據具體的Engine接口而定,可能是一個密鑰ID字符串,可能是一個公鑰文件,也可能是沒有任何意義的文件。如果你在執行公鑰解密(verify)操作或者公鑰加密(encrypt)操作,那么可以從nkey參數輸入一個公鑰而不是私鑰,使用pubin選項就可以告訴指令程序將要輸入的文件是公鑰文件。如果你希望使用一個證書里面的公鑰文件,那么可以使用-certin選項告訴指令程序inkey選項指定將要輸入的文件是一個證書文件。同樣,證書文件的格式可以通過keyform選項來指定,目前支持的證書格式包括DER編碼、PEM編碼、NET編碼和PKCS#12編碼格式四種。
數據補齊方式選項pkcs、ssl、oaep和raw
- 所謂數據補齊方式是指在利用RSA密鑰進行數據加密的時候,總是要求被加密數據長度跟RSA密鑰長度相同,但是輸入數據通常不是正好跟RSA密鑰長度相同,所以需要將不同長度的被加密數據補齊成跟密鑰長度相同的數據然后再進行加密;
- 當然,如果數據超出RSA密鑰長度,則需要自己預先分割。
- OpenSSL目前支持的補齊方式包括PKCS#1v1.5規定的方式、SSL協議規定的補齊方式、OAEP補齊方式和不使用補齊的方式。默認的數據補齊方式是PKCS#1v1.5。
- PKCS#1v1.5補齊方式是目前使用最廣泛的補齊方式,如果要用PKCS#1v1.5補齊方式,那么可以在指令中使用-pkcs選項。SSL協議規定的補齊方式是PKCS#1v1.5的修訂版,本質上區別不大,使用-ssl選項調用該種方式。這兩種基于PKCS#1v1.5的補齊方式都要求每次加密輸入的實際數據長度小于密鑰長度-11字節。
- OAEP方式是PKCS#1v2.0規定的新補齊方式,對于新的應用程序,一般來說推薦這種新的方式。要用這種方式,在指令中使用-oaep選項。該種補齊方式要求每次加密輸入的數據長度不能超過密鑰長度-41字節的長度。
- 最后,如果你不愿意使用任何補齊方式,那么-raw選項是你的選擇。但是,如不使用補齊方式,數據長度必須跟RSA密鑰長度相同。需要注意的是,如果執行的是簽名操作(RSA私鑰加密),那么只能使用PKCS#1v1.5的補齊方式或者不使用補齊方式。
engine選項
- 與其他OpenSSL指令一樣,rsautl指令也提供了對Engine的支持,可以通過Engine機制使用第三方算法庫或者硬件設備而不是OpenSSL本身的RSA算法進行加密、解密、簽名和驗證信息。
- engine選項后面應該給出有數的Engine設備ID,該ID一般是一個簡短的描述字符串,由Engine接口代碼決定。在該選項給定了有效的Engine接口設備之后,rsautl有兩個方面會受到影響。首先是RSA密鑰的獲取會受到影響。如果在使用了engine選項后,keyform中指定了密鑰的輸入格式是Engine格式,那么指令將試圖從Engine設備中獲取加密密鑰。這時候inkey選項指定的密鑰文件內容就根據具體的Engine接口要求而定。其次,如果使用了engine選項,而且Engine設備支持RSA的公鑰加密、私鑰解密、私鑰加密和公鑰解密的函數的全部或其中一部分,那么就會啟用Engine設備執行加密或者解密的操作,而不是使用OpenSSL的RSA算法。當然,如果Engine不支持或者只支持其中的一部分加密操作,那么不支持的部分就會調用OpenSSL算法庫本身的RSA加密操作。
其他選項
- 如果你希望輸出數據的十六進制的解析信息,那么可以使用hexdump選項來實現。使用asn1 parse可以看到使用ASN.1編碼(事實上一般是DER編碼)的數據對象的明文解析和對應的編碼數據,該選項在跟verify選項一起使用的時候比較有用,可以用來查看驗證的簽名的信息。上述兩個選項一般來說在執行解密操作的時候意義更大一些,否則只是一些看起來沒有意義的亂碼。有時候你可能想把輸入的數據顛倒順序后再進行加密或解密操作,比如把“123456789”變成“987654321”,那么可以使用rev選項實現你這個奇怪的想法。也就是說,如果你使用了rev選項,雖然你輸入的數據是“123456789”,事實上你加密的數據是“987654321”。