OpenSSL 之 RSA 相關命令學習筆記 原

作者: Angus.Fenying <[email protected]>

日期: 2016-11-10 10:35 PM

本文介紹 OpenSSL 命令行進行 RSA 加密、解密、簽名、驗證的操作,但不涉及 RSA 算法原理解析,如有興趣,可以閱讀阮一峯的《RSA算法原理》。如果你只想知道 RSA 是什麼,那麼你只要記住:RSA 是一種加密算法,使用兩個密鑰,一個叫公鑰,一個 叫私鑰,使用公鑰加密的密文只有使用私鑰纔可以解密,反之亦然。

Section 0: 生成隨機文件

由於 OpenSSL 創建密鑰文件是隨機生成的,因此有必要爲之提供一份隨機數據源。

可以用 openssl 的 rand 命令創建一個 64MB 的隨機文件,保存爲文件 randSrc.bin

openssl rand -out ./randSrc.bin 67108864

還可以使用 -base64 或者 -hex 兩個參數之一指定輸出格式爲 BASE64 或者 HEX。

Section 1: 生成一個密鑰文件

小貼士:

  1. 根據目前的普遍需求,應當使用 AES256 爲加密標準。
  2. 通常 RSA 私鑰文件命名爲 name.pem,公鑰文件名爲 name_pub.pem
  3. OpenSSL 生成的密鑰文件默認是 PEM 格式的。
openssl genrsa \
    -rand randSrc.bin \
    -aes256 \
    -out rsa.pem 2048

這個命令的意思是:

  • genrsa: 生成 RSA 密鑰文件。
  • -aes256: 使用 AES256 算法加密生成的密鑰文件, 因此你需要輸入加密用的密碼(並記住)。
  • -rand randSrc.bin 使用文件 randSrc.bin 作爲隨機數來源。
  • -out rsa.pem: 將生成的密鑰文件保存爲 rsa.pem
  • 2048: 生成 2048 Bits 的 RSA 密鑰文件。

2048 Bits 是指 RSA 算法裏 N 的長度,而不是說公鑰和私鑰都是 2048 Bits。

生成文件樣例:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,A6F8DD9D1D994363907C278CDF9B644C

MfsPjXK6izOmmzMseG3M2aBKque20ao13+oFg/JdJtlCK0Vb11hLqq8h/ICnY3lI
z1xuBKiXVykl521YumeTS6C+WtSkb71cy1u6lHBwdO44tWxklEqcl1sLYIWKyNaB
VgKmS4BhfuUq8XlSt3LnuQT/BJWPP7+GUUaZG6/stMWAx+XBg9mMahxGCqo7aRcz
...............
nLGRE27iklwGgSagaK40FDiSe69HcIBkHCUQYaYtXQzHNgjoQRkcotzo+vxM7XcL
5y5DHwA8IFwt9c5f14lxZ2cXF9p54JA3UMy+T7XggINDgBFuOPR/U3eBS2x6hHW6
eoGX+khw+s5atpNJaF4s6n2ViDseQsW+b8NfSdlX0j5f5xSasFcYgFsDZtBy/FqZ
-----END RSA PRIVATE KEY-----

這是一個密鑰文件,而不是一個純粹的私鑰文件,它包含了完整的密鑰信息,即是說,裏面 既有公鑰也有私鑰。但是隻能把它當成私鑰使用,公鑰部分請參考 Section 3

Section 2: 去除密鑰文件的密碼

Section 1 生成的密鑰文件中提取沒有密碼的密鑰文件,以便給 Nginx 等服務器使用。

openssl rsa -in rsa.pem -out rsa_pri.pem

Section 3: 根據私鑰生成公鑰

Section 1 生成的私鑰文件中提取公鑰文件。

openssl rsa -in rsa.pem -pubout -out rsa_pub.pem

Section 4: 使用公鑰加密

RSA 加密和解密都是使用 openssl 的 rsautl 命令。

Section 3 裏面生成了公鑰文件 rsa_pub.pem,下面使用它進行加密。 (先生成個數據文件)

echo 1234567890 > test.txt
md5sum test.txt
openssl rsautl \
    -encrypt \
    -in test.txt \
    -out test.secret \
    -pubin \
    -inkey rsa_pub.pem

可以看到源文件 test.txt 的 MD5 值爲 7c12772809c1c0c3deda6103b10fdfa0

源文件 test.txt 只有 10 個字節大小,但是加密結果文件 test.secret* 居然有 256 字節(2048 位長),這是因爲 RSA 密鑰是 2048 位長度的,而 RSA 加解密算法的操作 單位必須和密鑰長度一致。所以加密結果的大小一定和密鑰長度的一致。所以加密長度必須小於 密鑰長度 - 填充長度

關於填充數據,默認使用 PKCS#1 v1.5 填充格式。

Section 5: 使用私鑰解密

Section 1 裏面生成了密鑰文件 rsa.pem,下面使用它進行加密。

openssl rsautl -decrypt -in test.secret -out test.raw -inkey rsa.pem
md5sum test.raw

這裏使用的是帶密碼的密鑰文件,因此需要輸入 AES 密碼先把密鑰文件解密出來。如果使用的是 Section 2 中生成的無密碼密鑰文件,那麼則不需要輸入密碼了。

可以看到解密出來的文件 test.raw 的 MD5 值爲 7c12772809c1c0c3deda6103b10fdfa0

Section 6: 使用私鑰簽名

加解密是使用公鑰加密,私鑰解密,因爲公鑰是公開的,私鑰是保密的。簽名和校驗則反過來, 私鑰簽名,公鑰校驗。

這裏假設你要發送消息給你朋友,消息存在文件 test.txt 中,你已經擁有了你朋友的 公鑰文件 fr_pub.pem

那麼先用他的公鑰對文件進行加密:

openssl rsautl -encrypt -in test.txt -out test.msg -pubin -inkey fr_pub.pem

得到了加密後的文件 test.msg,下面使用你自己的私鑰進行簽名。

先用 SHA256 算法生成文件的哈希校驗碼:

openssl sha256 -out test.hash test.msg

得到了哈希校驗文件 test.hash,內容如下:

SHA256(test.msg)= ************************

下面使用 RSA 私鑰對其進行簽名:

openssl pkeyutl \
    -sign \
    -in test.hash \
    -out test.sign \
    -inkey rsa_raw.pem

或者

openssl rsautl \
    -sign \
    -in test.hash \
    -out test.sign \
    -inkey rsa_raw.pem

RSA 私鑰簽名的實質是:使用 RSA 私鑰對數據的哈希校驗碼進行加密,這樣就可以用 對應的 RSA 公鑰解密得到數據的哈希校驗碼。

得到了簽名後的文件 test.sign,將它和 test.msgrsa_pub.pem 一起發給你的朋友。

Section 7: 使用公鑰校驗

現在你的朋友收到了你發給他的三個文件,分別是:公鑰、簽名、消息。現在他怎麼確定 消息是發給他的呢?當然是使用公鑰校驗啦。

首先,他同樣使用 openssl 生成文件 test.msg 的哈希校驗碼。

openssl sha256 -out test.hash test.msg

然後使用你的公鑰文件對其進行校驗:

openssl pkeyutl \
    -verify \
    -in test.hash \
    -sigfile test.sign \
    -pubin \
    -inkey rsa_pub.pem

如果校驗通過,則會看到提示:Signature Verified Successfully

然後他再使用他的私鑰解密 test.msg 文件即可得到你發給他的消息了。

這裏不使用 openssl rsautl -verify 命令,因爲 rsautl-verify 指令 僅僅是將輸入的文件用公鑰解密,但不與計算出來的哈希校驗碼進行比較,不如 pkeyutl 的 -verify 方便:

openssl rsautl \
    -verify \
    -in test.sign \
    -pubin \
    -inkey rsa_pub.pem

前面說了,rsa.pem 裏面既包含私鑰又包含公鑰,這裏可以小小地證明一下。 直接使用 rsa_raw.pem 文件進行簽名校驗。

openssl pkeyutl \
    -verify \
    -in test.hash \
    -sigfile test.sign \
    -pubin \
    -inkey rsa_raw.pem

如何,結果是不是一樣呢?

那麼,問題來了。如果傳輸過程被人攔截了怎麼辦?這就是下一篇文章的內容了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章