1、非對稱加密演算法概述
非對稱加密演算法也稱公開金鑰演算法,其解決了對稱加密演算法金鑰分配的問題,非對稱加密演算法基本特點如下:
1、加密金鑰和解密金鑰不同
2、金鑰對中的一個金鑰可以公開
3、根據公開金鑰很難推算出私人金鑰
根據非對稱加密演算法的特點,可使用者數字簽名、金鑰交換、資料加密。但是由於非對稱加密演算法較對稱加密演算法加密速度慢很多,故最常用的用途是數字簽名和金鑰交換。
目前常用的非對稱加密演算法有RSA, DH和DSA三種,但並非都可以用於金鑰交換和數字簽名。而是RSA可用於數字簽名和金鑰交換,DH演算法可用於金鑰交換,而DSA演算法專門使用者數字簽名。
openssl支援以上三種演算法,併為三種演算法提供了豐富的指令集,本章主要介紹RSA演算法及相關指令
2、RSA演算法相關指令及用法
RSA雖然可以數字簽名、金鑰交換和資料加密,但是RSA加密資料速度慢,通常不使用RSA加密資料。所以最常用的功能就是數字簽名和金鑰交換,拋開數字簽名和金鑰交換的概念,實質上就是使用公鑰加密還是使用私鑰加密的區別。所以我們只要記住一句話:“公鑰加密,私鑰簽名”。
公鑰加密:用途是金鑰交換,使用者A使用使用者B的公鑰將少量資料加密傳送給B,B用自己的私鑰解密資料
私鑰簽名:用途是數字簽名,使用者A使用自己的私鑰將資料的摘要資訊加密一併傳送給B,B用A的公鑰解密摘要資訊並驗證
opessl中RSA演算法指令主要有三個,其他指令雖有涉及,但此處不再詳述。
指令 | 功能 |
genrsa | 生成並輸入一個RSA私鑰 |
rsa | 處理RSA金鑰的格式轉換等問題 |
rsautl | 使用RSA金鑰進行加密、解密、簽名和驗證等運算 |
2.1 genrsa指令說明
genrsa用於生成金鑰對,其用法如下
- xlzh@cmos:~$ openssl genrsa -
- usage: genrsa [args] [numbits] //金鑰位數,建議1024及以上
- -des encrypt the generated key with DES in cbc mode //生成的金鑰使用des方式進行加密
- -des3 encrypt the generated key with DES in ede cbc mode ( bit key) //生成的金鑰使用des3方式進行加密
- -seed
- encrypt PEM output with cbc seed //生成的金鑰還是要seed方式進行
- -aes128, -aes192, -aes256
- encrypt PEM output with cbc aes //生成的金鑰使用aes方式進行加密
- -camellia128, -camellia192, –camellia256
- encrypt PEM output with cbc camellia //生成的金鑰使用camellia方式進行加密
- -out file output the key to 'file //生成的金鑰檔案,可從中提取公鑰
- -passout arg output file pass phrase source //指定金鑰檔案的加密口令,可從檔案、環境變數、終端等輸入
- -f4 use F4 (0x10001) for the E value //選擇指數e的值,預設指定該項,e值為65537 - use for the E value //選擇指數e的值,預設值為65537,使用該選項則指數指定為3
- -engine e use engine e, possibly a hardware device. //指定三方加密庫或者硬體
- -rand file:file:...
- load the file (or the files in the directory) into //產生隨機數的種子檔案
- the random number generator
可以看到genrsa指令使用較為簡單,常用的也就有指定加密演算法、輸出金鑰檔案、加密口令。我們僅舉一個例子來說明
- /*
- * 指定金鑰檔案rsa.pem
- * 指定加密演算法aes128
- * 指定加密金鑰123456
- * 指定金鑰長度1024
- **/
- xlzh@cmos:~$ openssl genrsa -out rsa.pem -aes128 -passout pass:
- Generating RSA private key, bit long modulus
- ...............................................................++++++
- .................................++++++
- e is (0x10001) // 預設模式65537
- /*加密後的金鑰檔案有加密演算法等資訊*/
- xlzh@cmos:~$ cat rsa.pem
- -----BEGIN RSA PRIVATE KEY-----
- Proc-Type: ,ENCRYPTED
- DEK-Info: AES--CBC,4C23682B0D34D339ED7E44819A70B4F9
- c9uHqqWbkcw3hjdQ/6fGuJcOFchd4+KfVZoJnnISnJBAhv3CelFAksKb2RKa5GoC
- 4Eq6SykCCSH8OboPoPBjd1ZdAsDl1Pio0vIJfAoQ4NmaRJ61+6onJ/HAx2NFTDjN
- yrmsGOWejB6A3MT4KiXrvICnkKMsUY1Qp6ln2qOeVynmxeWAWiVZnjfm0OkScL1K
- RGSuL32vecN5b1S8fZTYJTS3PQxjmyaw65zLX+8mUObanL9WhSLTz2eo/6xTzRbD
- iOGMolfP/3ObqIAS3007qV48CtwWrlAa+RpbMVIiESN7BforOaNbh0s5NVuUnXYs
- hx90iZj2M1L4i5SP8jKBunXPK6CHQtUQXpMH06nhoMNyZPtRQegFgZlwVOpOfoS5
- khGAjJPnEXI7ah8oCNYO21JV6SlMFxK1lUeS3xCvM8Cd/zVBSzD7jg+axBJr+LpO
- rhpmEFkStXHtFo3OK3BoyQHIzYEYH4S59xWO+dfrb2zUvkKsQKkV+TFMSZpr7b7U
- iegUcK3NrbcWDApfTYmf/edublJBv816to+hYQLhXKfuzP5iMJmjnubhrXrA6S47
- 7XN6nil9DGWzUEMPnH6Brc8mj7JwFtxdpWDN2pY+VcJ04O98fO08c+4eSS3u0Y9f
- TyxYy1C9nIWxF+t2Dulq94N4AQ2uyTXoVNhrmDYrJ9BUCugg6zx6xtU24aSGFvtn
- ikgAU8JCX0GkcwU60tTLSxPNAWhNxJSJ5n7BXaV6QQ1GOiiKQlJAcRv2PMxNqVgK
- poVq742+awsichrwqE5VIFW9AdSMyIT7w06IogyUrS++FmFS6qPtT3ZbFZakzkd
- -----END RSA PRIVATE KEY-----
- xlzh@cmos:~$
2.2 rsa指令說明
rsa指令使用者管理生成的金鑰,其用法如下
- xlzh@cmos:~$ openssl rsa -
- unknown option -
- rsa [options] <infile >outfile
- where options are
- -inform arg input format - one of DER NET PEM //輸入檔案格式,預設pem格式
- -outform arg output format - one of DER NET PEM //輸入檔案格式,預設pem格式
- -in arg input file //輸入檔案
- -sgckey Use IIS SGC key format //指定SGC編碼格式,相容老版本,不應再使用
- -passin arg input file pass phrase source //指定輸入檔案的加密口令,可來自檔案、終端、環境變數等
- -out arg output file //輸出檔案
- -passout arg output file pass phrase source //指定輸出檔案的加密口令,可來自檔案、終端、環境變數等
- -des encrypt PEM output with cbc des //使用des加密輸出的檔案
- -des3 encrypt PEM output with ede cbc des using bit key //使用des3加密輸出的檔案
- -seed encrypt PEM output with cbc seed //使用seed加密輸出的檔案
- -aes128, -aes192, -aes256
- encrypt PEM output with cbc aes //使用aes加密輸出的檔案
- -camellia128, -camellia192, -camellia256
- encrypt PEM output with cbc camellia //使用camellia加密輸出的檔案呢
- -text print the key in text //以明文形式輸出各個引數值
- -noout don't print key out //不輸出金鑰到任何檔案
- -modulus print the RSA key modulus //輸出模數指
- -check verify key consistency //檢查輸入金鑰的正確性和一致性
- -pubin expect a public key in input file //指定輸入檔案是公鑰
- -pubout output a public key //指定輸出檔案是公鑰
- -engine e use engine e, possibly a hardware device. //指定三方加密庫或者硬體
- xlzh@cmos:~$
rsa指令操作示例如下
1、rsa新增和去除金鑰的保護口令
- /*生成不加密的RSA金鑰*/
- xlzh@cmos:~/test$ openssl genrsa -out RSA.pem
- Generating RSA private key, bit long modulus
- ..............++++++++++++
- .....++++++++++++
- e is (0x10001)
- /*為RSA金鑰增加口令保護*/
- xlzh@cmos:~/test$ openssl rsa -in RSA.pem -des3 -passout pass: -out E_RSA.pem
- writing RSA key
- /*為RSA金鑰去除口令保護*/
- xlzh@cmos:~/test$ openssl rsa -in E_RSA.pem -passin pass: -out P_RSA.pem
- writing RSA key
- /*比較原始後的RSA金鑰和去除口令後的RSA金鑰,是一樣*/
- xlzh@cmos:~/test$ diff RSA.pem P_RSA.pem
2、修改金鑰的保護口令和演算法
- /*生成RSA金鑰*/
- xlzh@cmos:~/test$ openssl genrsa -des3 -passout pass: -out RSA.pem
- Generating RSA private key, bit long modulus
- ..................++++++++++++
- ......................++++++++++++
- e is (0x10001)
- /*修改加密演算法為aes128,口令是123456*/
- xlzh@cmos:~/test$ openssl rsa -in RSA.pem -passin pass: -aes128 -passout pass: -out E_RSA.pem
- writing RSA key
3、檢視金鑰對中的各個引數
- xlzh@cmos:~/test$ openssl rsa -in RSA.pem -des -passin pass: -text -noout
4、提取金鑰中的公鑰並列印模數值
- /*提取公鑰,用pubout引數指定輸出為公鑰*/
- xlzh@cmos:~/test$ openssl rsa -in RSA.pem -passin pass: -pubout -out pub.pem
- writing RSA key
- /*列印公鑰中模數值*/
- xlzh@cmos:~/test$ openssl rsa -in pub.pem -pubin -modulus -noout
- Modulus=C35E0B54041D78466EAE7DE67C1DA4D26575BC1608CE6A199012E11D10ED36E2F7C651D4D8B40D93691D901E2CF4E21687E912B77DCCE069373A7F6585E946EF
5、轉換金鑰的格式
- /*把pem格式轉化成der格式,使用outform指定der格式*/
- xlzh@cmos:~/test$ openssl rsa -in RSA.pem -passin pass: -des -passout pass: -outform der -out rsa.der
- writing RSA key
- /*把der格式轉化成pem格式,使用inform指定der格式*/
- xlzh@cmos:~/test$ openssl rsa -in rsa.der -inform der -passin pass: -out rsa.pem
2.3 rsautl指令說明
上述兩個指令是金鑰的生成及管理作用,rsautl則是真正用於金鑰交換和數字簽名。實質上就是使用RSA公鑰或者私鑰加密。
而無論是使用公鑰加密還是私鑰加密,RSA每次能夠加密的資料長度不能超過RSA金鑰長度,並且根據具體的補齊方式不同輸入的加密資料最大長度也不一樣,而輸出長度則總是跟RSA金鑰長度相等。RSA不同的補齊方法對應的輸入輸入長度如下表
資料補齊方式 | 輸入資料長度 | 輸出資料長度 | 引數字串 |
PKCS#1 v1.5 | 少於(金鑰長度-11)位元組 | 同金鑰長度 | -pkcs |
PKCS#1 OAEP | 少於(金鑰長度-11)位元組 | 同金鑰長度 | -oaep |
PKCS#1 for SSLv23 | 少於(金鑰長度-11)位元組 | 同金鑰長度 | -ssl |
不使用補齊 | 同金鑰長度 | 同金鑰長度 | -raw |
rsautl指令用法如下
- xlzh@cmos:~$ openssl rsautl -
- Usage: rsautl [options]
- -in file input file //輸入檔案
- -out file output file //輸出檔案
- -inkey file input key //輸入的金鑰
- -keyform arg private key format - default PEM //指定金鑰格式
- -pubin input is an RSA public //指定輸入的是RSA公鑰
- -certin input is a certificate carrying an RSA public key //指定輸入的是證書檔案
- -ssl use SSL v2 padding //使用SSLv23的填充方式
- -raw use no padding //不進行填充
- -pkcs use PKCS# v1. padding (default) //使用V1.5的填充方式
- -oaep use PKCS# OAEP //使用OAEP的填充方式
- -sign sign with private key //使用私鑰做簽名
- -verify verify with public key //使用公鑰認證簽名
- -encrypt encrypt with public key //使用公鑰加密
- -decrypt decrypt with private key //使用私鑰解密
- -hexdump hex dump output //以16進位制dump輸出
- -engine e use engine e, possibly a hardware device. //指定三方庫或者硬體裝置
- -passin arg pass phrase source //指定輸入的密碼
rsautl操作示例如下:
1、使用rsautl進行加密和解密操作
- /*生成RSA金鑰*/
- xlzh@cmos:~/test$ openssl genrsa -des3 -passout pass: -out RSA.pem
- Generating RSA private key, bit long modulus
- ............++++++++++++
- ...++++++++++++
- e is (0x10001)
- /*提取公鑰*/
- xlzh@cmos:~/test$ openssl rsa -in RSA.pem -passin pass: -pubout -out pub.pem
- writing RSA key
- /*使用RSA作為金鑰進行加密,實際上使用其中的公鑰進行加密*/
- xlzh@cmos:~/test$ openssl rsautl -encrypt -in plain.txt -inkey RSA.pem -passin pass: -out enc.txt
- /*使用RSA作為金鑰進行解密,實際上使用其中的私鑰進行解密*/
- xlzh@cmos:~/test$ openssl rsautl -decrypt -in enc.txt -inkey RSA.pem -passin pass: -out replain.txt
- /*比較原始檔案和解密後文件*/
- xlzh@cmos:~/test$ diff plain.txt replain.txt
- /*使用公鑰進行加密*/
- xlzh@cmos:~/test$ openssl rsautl -encrypt -in plain.txt -inkey pub.pem -pubin -out enc1.txt
- /*使用RSA作為金鑰進行解密,實際上使用其中的私鑰進行解密*/
- xlzh@cmos:~/test$ openssl rsautl -decrypt -in enc1.txt -inkey RSA.pem -passin pass: -out replain1.txt
- /*比較原始檔案和解密後文件*/
- xlzh@cmos:~/test$ diff plain.txt replain1.txt
在進行這個實驗的時候有個疑惑,為什麼相同的明文,使用金鑰加密和公鑰加密後的密文結果不一樣?在網上查詢了下,是因為rsa公鑰加密的時候根據填充模式填充隨機數,導致每次加密結果不同。
2、使用rsautl進行簽名和驗證操作
- /*提取PCKS8格式的私鑰*/
- xlzh@cmos:~/test$ openssl pkcs8 -topk8 -in RSA.pem -passin pass: -out pri.pem -nocrypt
- /*使用RSA金鑰進行簽名,實際上使用私鑰進行加密*/
- xlzh@cmos:~/test$ openssl rsautl -sign -in plain.txt -inkey RSA.pem -passin pass: -out sign.txt
- /*使用RSA金鑰進行驗證,實際上使用公鑰進行解密*/
- xlzh@cmos:~/test$ openssl rsautl -verify -in sign.txt -inkey RSA.pem -passin pass: -out replain.txt
- /*對比原始檔案和簽名解密後的檔案*/
- xlzh@cmos:~/test$ diff plain.txt replain.txt
- /*使用私鑰進行簽名*/
- xlzh@cmos:~/test$ openssl rsautl -sign -in plain.txt -inkey pri.pem -out sign1.txt
- /*使用公鑰進行驗證*/
- xlzh@cmos:~/test$ openssl rsautl -verify -in sign1.txt -inkey pub.pem -pubin -out replain1.txt
- /*對比原始檔案和簽名解密後的檔案*/
- xlzh@cmos:~/test$ cat plain replain1.txt
要注意這裡的簽名和驗證過程其本質上是加解密操作,不是標準意義上的簽名和驗證。標準意義上簽名和驗證是需要增加摘要操作的,後續文章再詳細闡述。
3、小結
我們可以看到上述指令的引數中有涉及到證書相關的內容,等到後期我們介紹CA相關內容的時候在進行補充。