本文由雲+社群發表
作者:mariolu
一、什麼是PSS模式?
1.1、兩種簽名方式之一RSA-PSS
PSS (Probabilistic Signature Scheme)私鑰簽名流程的一種填充模式。目前主流的RSA簽名包括RSA-PSS和RSA-PKCS#1 v1.5。相對應PKCS(Public Key Cryptography Standards)是一種能夠自我從簽名,而PSS無法從簽名中恢恢復原來的簽名。openssl-1.1.x以後預設使用更安全的PSS的RSA簽名模式。
1.2、填充的必要性
RSA演算法比較慢,一般用於非對稱加密的private key簽名和public key驗證。因RSA演算法沒有加入亂數,當出現重複性的原始資料,攻擊者會通過相同加密密文而猜測出原文,因此匯入padding的機制來加強安全性。
TLS流程中的金鑰材料若不進行填充而直接加密,那麼顯然相同的key,會得到相同的密文。這種在語義上來說,是不安全的。以下例子說明了無填充模式的安全漏洞。
- m:明文
- e,n:RSA引數(公鑰)
- d:RSA引數(私鑰)
- c:網路傳輸密文
加密方加密m:c = m^e mod n,傳輸c
解密方解密c:m = c^d mod n,還原m
- c':篡改密文
- k:篡改碼
由於c在網路上傳輸,如果網路上有人對其進行c' = c*k^e mod n,這樣的替換
那麼解密方將得到的結果是
(c*k^e)^d mod n
= (c^d mod n)* (k^ed mod n)
= m*k
即中間人有辦法控制m。
1.3、PSS的基本要素
使用PSS模式的RSA簽名流程如下:
圖1、RSA-PSS的填充模式相比較PKCS#1 v1.5的padding簡單許多:
圖2、RSA-PKCS#v1.5的填充模式PSS的一些概念:
- hash演算法,一般使用SHA-1
- MGF函式(mask generation function)。預設是MGF1。
- salt length,一般由hLen決定。當為0時,簽名值變成了唯一確定的。
- 截斷符號,一般是0xbc
二、RSA簽名實際操作
這節例子中所涉及到的檔案說明:
/tmp/wildcard_domain.sports.qq.com.v2.key:私鑰
/tmp/pub: 公鑰
/tmp/data: 明文
/tmp/endata: 密文
/tmp/sign: 簽名
/tmp/de_sign: 解簽名
2.1、前期準備:公鑰和私鑰
- 通過key檔案提取出public key
openssl rsa -in /usr/local/services/ssl_agent/ca/wildcard_domain.sports.qq.com.v2.key -pubout -out /tmp/pub
複製程式碼
- 原始資料:
echo -n "1234567890" > /tmp/data
- 這樣就有一對公鑰和私鑰,用來測試RSA加密解密(encrypt、decrypt)和簽名驗證(sign,verify)
- RSA加密的兩種演算法分別是RSAES-PKCS-v1_5 and RSAES-OAEP。
2.2、加密和解密(encrypt,decrypt)
- 加密:
openssl rsautl -pubin -inkey /tmp/data -in /tmp/data -encrypt -out /tmp/endata
複製程式碼
- 解密,用private key解密,得到原本的值:
openssl rsautl -inkey /tmp/wildcard_domain.sports.qq.com.v2.key -in /tmp/en_data -decrypt
複製程式碼
2.3、簽名和驗證(sign, verify)
簽名過程包括hash和加密。hash函式一般使用sha1。這樣輸入明文,直接生成sign簽名。
如果是私鑰簽名所做的事就是先hash再加密,選擇一種hash演算法把原始訊息計算後成ASN1格式,再把這個資料用private key加密後送出,資料本身不加密,這種方式主要是用來驗證資料來源是否可信任的,送出時把原始資料和簽名一起送出。
- 簽名:
openssl sha1 -sign /tmp/wildcard_domain.sports.qq.com.v2.key /tmp/data > /tmp/data/sign/tmp/data/sign
複製程式碼
- 解開簽名:
openssl rsautl -pubin -inkey /tmp/pub -in sign -verify -out /tmp/de_sign
複製程式碼
用public key解開簽名,並且保留padding
openssl rsautl -pubin -inkey /tmp/pub -in /tmp/sign -encrypt -raw -hexdump
複製程式碼
使用解開ASN1解開簽名,或者簽名後用ASN1工具解析
openssl rsautl -pubin -inkey /tmp/pub -in /tmp/sign -verify -asn1parse
複製程式碼
或者:
openssl asn1parse -inform der -in /tmp/de_sign
複製程式碼
和本地sha1對比
openssl sha1 /tmp/data
複製程式碼
如果兩者hash結果是一樣,那麼確定簽名送過來是正確的。
2.4、openssl rsautl工具支援的填充模式
openssl rsautl --help,可以看到支援的padding模式有,在rsautl加上以下選項可以重複做2.2~2.3的實驗。
-ssl Use SSL v2 padding
-raw Use no padding
-pkcs Use PKCS#1 v1.5 padding (default)
-oaep Use PKCS#1 OAEP
複製程式碼
三、PSS填充模式的特點
PSS是RSA的填充模式中的一種。
完整的RSA的填充模式包括:
RSA_SSLV23_PADDING(SSLv23填充)
RSA_NO_PADDING(不填充)
RSA_PKCS1_OAEP_PADDING (RSAES-OAEP填充,強制使用SHA1,加密使用)
RSA_X931_PADDING(X9.31填充,簽名使用)
RSA_PKCS1_PSS_PADDING(RSASSA-PSS填充,簽名使用)
RSA_PKCS1_PADDING(RSAES-PKCS1-v1_5/RSASSA-PKCS1-v1_5填充,簽名可使用)
複製程式碼
其中主流的填充模式是PKCS1和PSS模式。
PSS的優缺點如下:
- PKCS#1 v1.5比較簡易實現,但是缺少security proof。
- PSS更安全,所以新版的openssl-1.1.x優先使用PSS進行私鑰簽名(具體在ssl握手的server key exchange階段)
此文已由騰訊雲+社群在各渠道釋出
獲取更多新鮮技術乾貨,可以關注我們騰訊雲技術社群-雲加社群官方號及知乎機構號