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用於生成金鑰對,其用法如下

  1. xlzh@cmos:~$ openssl genrsa -
  2. usage: genrsa [args] [numbits] //金鑰位數,建議1024及以上
  3. -des encrypt the generated key with DES in cbc mode //生成的金鑰使用des方式進行加密
  4. -des3 encrypt the generated key with DES in ede cbc mode ( bit key) //生成的金鑰使用des3方式進行加密
  5. -seed
  6. encrypt PEM output with cbc seed //生成的金鑰還是要seed方式進行
  7. -aes128, -aes192, -aes256
  8. encrypt PEM output with cbc aes //生成的金鑰使用aes方式進行加密
  9. -camellia128, -camellia192, camellia256
  10. encrypt PEM output with cbc camellia //生成的金鑰使用camellia方式進行加密
  11. -out file output the key to 'file //生成的金鑰檔案,可從中提取公鑰
  12. -passout arg output file pass phrase source //指定金鑰檔案的加密口令,可從檔案、環境變數、終端等輸入
  13. -f4 use F4 (0x10001) for the E value //選擇指數e的值,預設指定該項,e值為65537 - use for the E value //選擇指數e的值,預設值為65537,使用該選項則指數指定為3
  14. -engine e use engine e, possibly a hardware device. //指定三方加密庫或者硬體
  15. -rand file:file:...
  16. load the file (or the files in the directory) into //產生隨機數的種子檔案
  17. the random number generator

可以看到genrsa指令使用較為簡單,常用的也就有指定加密演算法、輸出金鑰檔案、加密口令。我們僅舉一個例子來說明

  1. /*
  2. * 指定金鑰檔案rsa.pem
  3. * 指定加密演算法aes128
  4. * 指定加密金鑰123456
  5. * 指定金鑰長度1024
  6. **/
  7. xlzh@cmos:~$ openssl genrsa -out rsa.pem -aes128 -passout pass:
  8. Generating RSA private key, bit long modulus
  9. ...............................................................++++++
  10. .................................++++++
  11. e is (0x10001) // 預設模式65537
  12. /*加密後的金鑰檔案有加密演算法等資訊*/
  13. xlzh@cmos:~$ cat rsa.pem
  14. -----BEGIN RSA PRIVATE KEY-----
  15. Proc-Type: ,ENCRYPTED
  16. DEK-Info: AES--CBC,4C23682B0D34D339ED7E44819A70B4F9
  17.  
  18. c9uHqqWbkcw3hjdQ/6fGuJcOFchd4+KfVZoJnnISnJBAhv3CelFAksKb2RKa5GoC
  19. 4Eq6SykCCSH8OboPoPBjd1ZdAsDl1Pio0vIJfAoQ4NmaRJ61+6onJ/HAx2NFTDjN
  20. yrmsGOWejB6A3MT4KiXrvICnkKMsUY1Qp6ln2qOeVynmxeWAWiVZnjfm0OkScL1K
  21. RGSuL32vecN5b1S8fZTYJTS3PQxjmyaw65zLX+8mUObanL9WhSLTz2eo/6xTzRbD
  22. iOGMolfP/3ObqIAS3007qV48CtwWrlAa+RpbMVIiESN7BforOaNbh0s5NVuUnXYs
  23. hx90iZj2M1L4i5SP8jKBunXPK6CHQtUQXpMH06nhoMNyZPtRQegFgZlwVOpOfoS5
  24. khGAjJPnEXI7ah8oCNYO21JV6SlMFxK1lUeS3xCvM8Cd/zVBSzD7jg+axBJr+LpO
  25. rhpmEFkStXHtFo3OK3BoyQHIzYEYH4S59xWO+dfrb2zUvkKsQKkV+TFMSZpr7b7U
  26. iegUcK3NrbcWDApfTYmf/edublJBv816to+hYQLhXKfuzP5iMJmjnubhrXrA6S47
  27. 7XN6nil9DGWzUEMPnH6Brc8mj7JwFtxdpWDN2pY+VcJ04O98fO08c+4eSS3u0Y9f
  28. TyxYy1C9nIWxF+t2Dulq94N4AQ2uyTXoVNhrmDYrJ9BUCugg6zx6xtU24aSGFvtn
  29. ikgAU8JCX0GkcwU60tTLSxPNAWhNxJSJ5n7BXaV6QQ1GOiiKQlJAcRv2PMxNqVgK
  30. poVq742+awsichrwqE5VIFW9AdSMyIT7w06IogyUrS++FmFS6qPtT3ZbFZakzkd
  31. -----END RSA PRIVATE KEY-----
  32. xlzh@cmos:~$

2.2 rsa指令說明

rsa指令使用者管理生成的金鑰,其用法如下

  1. xlzh@cmos:~$ openssl rsa -
  2. unknown option -
  3. rsa [options] <infile >outfile
  4. where options are
  5. -inform arg input format - one of DER NET PEM //輸入檔案格式,預設pem格式
  6. -outform arg output format - one of DER NET PEM //輸入檔案格式,預設pem格式
  7. -in arg input file //輸入檔案
  8. -sgckey Use IIS SGC key format //指定SGC編碼格式,相容老版本,不應再使用
  9. -passin arg input file pass phrase source //指定輸入檔案的加密口令,可來自檔案、終端、環境變數等
  10. -out arg output file //輸出檔案
  11. -passout arg output file pass phrase source //指定輸出檔案的加密口令,可來自檔案、終端、環境變數等
  12. -des encrypt PEM output with cbc des //使用des加密輸出的檔案
  13. -des3 encrypt PEM output with ede cbc des using bit key //使用des3加密輸出的檔案
  14. -seed encrypt PEM output with cbc seed //使用seed加密輸出的檔案
  15. -aes128, -aes192, -aes256
  16. encrypt PEM output with cbc aes //使用aes加密輸出的檔案
  17. -camellia128, -camellia192, -camellia256
  18. encrypt PEM output with cbc camellia //使用camellia加密輸出的檔案呢
  19. -text print the key in text //以明文形式輸出各個引數值
  20. -noout don't print key out //不輸出金鑰到任何檔案
  21. -modulus print the RSA key modulus //輸出模數指
  22. -check verify key consistency //檢查輸入金鑰的正確性和一致性
  23. -pubin expect a public key in input file //指定輸入檔案是公鑰
  24. -pubout output a public key //指定輸出檔案是公鑰
  25. -engine e use engine e, possibly a hardware device. //指定三方加密庫或者硬體
  26. xlzh@cmos:~$

rsa指令操作示例如下

1、rsa新增和去除金鑰的保護口令

  1. /*生成不加密的RSA金鑰*/
  2. xlzh@cmos:~/test$ openssl genrsa -out RSA.pem
  3. Generating RSA private key, bit long modulus
  4. ..............++++++++++++
  5. .....++++++++++++
  6. e is (0x10001)
  7. /*為RSA金鑰增加口令保護*/
  8. xlzh@cmos:~/test$ openssl rsa -in RSA.pem -des3 -passout pass: -out E_RSA.pem
  9. writing RSA key
  10. /*為RSA金鑰去除口令保護*/
  11. xlzh@cmos:~/test$ openssl rsa -in E_RSA.pem -passin pass: -out P_RSA.pem
  12. writing RSA key
  13. /*比較原始後的RSA金鑰和去除口令後的RSA金鑰,是一樣*/
  14. xlzh@cmos:~/test$ diff RSA.pem P_RSA.pem

2、修改金鑰的保護口令和演算法

  1. /*生成RSA金鑰*/
  2. xlzh@cmos:~/test$ openssl genrsa -des3 -passout pass: -out RSA.pem
  3. Generating RSA private key, bit long modulus
  4. ..................++++++++++++
  5. ......................++++++++++++
  6. e is (0x10001)
  7. /*修改加密演算法為aes128,口令是123456*/
  8. xlzh@cmos:~/test$ openssl rsa -in RSA.pem -passin pass: -aes128 -passout pass: -out E_RSA.pem
  9. writing RSA key

3、檢視金鑰對中的各個引數

  1. xlzh@cmos:~/test$ openssl rsa -in RSA.pem -des -passin pass: -text -noout

4、提取金鑰中的公鑰並列印模數值

  1. /*提取公鑰,用pubout引數指定輸出為公鑰*/
  2. xlzh@cmos:~/test$ openssl rsa -in RSA.pem -passin pass: -pubout -out pub.pem
  3. writing RSA key
  4. /*列印公鑰中模數值*/
  5. xlzh@cmos:~/test$ openssl rsa -in pub.pem -pubin -modulus -noout
  6. Modulus=C35E0B54041D78466EAE7DE67C1DA4D26575BC1608CE6A199012E11D10ED36E2F7C651D4D8B40D93691D901E2CF4E21687E912B77DCCE069373A7F6585E946EF

5、轉換金鑰的格式

  1. /*把pem格式轉化成der格式,使用outform指定der格式*/
  2. xlzh@cmos:~/test$ openssl rsa -in RSA.pem -passin pass: -des -passout pass: -outform der -out rsa.der
  3. writing RSA key
  4. /*把der格式轉化成pem格式,使用inform指定der格式*/
  5. 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指令用法如下

  1. xlzh@cmos:~$ openssl rsautl -
  2. Usage: rsautl [options]
  3. -in file input file //輸入檔案
  4. -out file output file //輸出檔案
  5. -inkey file input key //輸入的金鑰
  6. -keyform arg private key format - default PEM //指定金鑰格式
  7. -pubin input is an RSA public //指定輸入的是RSA公鑰
  8. -certin input is a certificate carrying an RSA public key //指定輸入的是證書檔案
  9. -ssl use SSL v2 padding //使用SSLv23的填充方式
  10. -raw use no padding //不進行填充
  11. -pkcs use PKCS# v1. padding (default) //使用V1.5的填充方式
  12. -oaep use PKCS# OAEP //使用OAEP的填充方式
  13. -sign sign with private key //使用私鑰做簽名
  14. -verify verify with public key //使用公鑰認證簽名
  15. -encrypt encrypt with public key //使用公鑰加密
  16. -decrypt decrypt with private key //使用私鑰解密
  17. -hexdump hex dump output //以16進位制dump輸出
  18. -engine e use engine e, possibly a hardware device. //指定三方庫或者硬體裝置
  19. -passin arg pass phrase source //指定輸入的密碼

rsautl操作示例如下:

1、使用rsautl進行加密和解密操作

  1. /*生成RSA金鑰*/
  2. xlzh@cmos:~/test$ openssl genrsa -des3 -passout pass: -out RSA.pem
  3. Generating RSA private key, bit long modulus
  4. ............++++++++++++
  5. ...++++++++++++
  6. e is (0x10001)
  7. /*提取公鑰*/
  8. xlzh@cmos:~/test$ openssl rsa -in RSA.pem -passin pass: -pubout -out pub.pem
  9. writing RSA key
  10. /*使用RSA作為金鑰進行加密,實際上使用其中的公鑰進行加密*/
  11. xlzh@cmos:~/test$ openssl rsautl -encrypt -in plain.txt -inkey RSA.pem -passin pass: -out enc.txt
  12. /*使用RSA作為金鑰進行解密,實際上使用其中的私鑰進行解密*/
  13. xlzh@cmos:~/test$ openssl rsautl -decrypt -in enc.txt -inkey RSA.pem -passin pass: -out replain.txt
  14. /*比較原始檔案和解密後文件*/
  15. xlzh@cmos:~/test$ diff plain.txt replain.txt
  16. /*使用公鑰進行加密*/
  17. xlzh@cmos:~/test$ openssl rsautl -encrypt -in plain.txt -inkey pub.pem -pubin -out enc1.txt
  18. /*使用RSA作為金鑰進行解密,實際上使用其中的私鑰進行解密*/
  19. xlzh@cmos:~/test$ openssl rsautl -decrypt -in enc1.txt -inkey RSA.pem -passin pass: -out replain1.txt
  20. /*比較原始檔案和解密後文件*/
  21. xlzh@cmos:~/test$ diff plain.txt replain1.txt

在進行這個實驗的時候有個疑惑,為什麼相同的明文,使用金鑰加密和公鑰加密後的密文結果不一樣?在網上查詢了下,是因為rsa公鑰加密的時候根據填充模式填充隨機數,導致每次加密結果不同。

2、使用rsautl進行簽名和驗證操作

  1. /*提取PCKS8格式的私鑰*/
  2. xlzh@cmos:~/test$ openssl pkcs8 -topk8 -in RSA.pem -passin pass: -out pri.pem -nocrypt
  3. /*使用RSA金鑰進行簽名,實際上使用私鑰進行加密*/
  4. xlzh@cmos:~/test$ openssl rsautl -sign -in plain.txt -inkey RSA.pem -passin pass: -out sign.txt
  5. /*使用RSA金鑰進行驗證,實際上使用公鑰進行解密*/
  6. xlzh@cmos:~/test$ openssl rsautl -verify -in sign.txt -inkey RSA.pem -passin pass: -out replain.txt
  7. /*對比原始檔案和簽名解密後的檔案*/
  8. xlzh@cmos:~/test$ diff plain.txt replain.txt
  9. /*使用私鑰進行簽名*/
  10. xlzh@cmos:~/test$ openssl rsautl -sign -in plain.txt -inkey pri.pem -out sign1.txt
  11. /*使用公鑰進行驗證*/
  12. xlzh@cmos:~/test$ openssl rsautl -verify -in sign1.txt -inkey pub.pem -pubin -out replain1.txt
  13. /*對比原始檔案和簽名解密後的檔案*/
  14. xlzh@cmos:~/test$ cat plain replain1.txt

要注意這裡的簽名和驗證過程其本質上是加解密操作,不是標準意義上的簽名和驗證。標準意義上簽名和驗證是需要增加摘要操作的,後續文章再詳細闡述。

3、小結

我們可以看到上述指令的引數中有涉及到證書相關的內容,等到後期我們介紹CA相關內容的時候在進行補充。