使用 openssl 進行數字簽名
我正在嘗試使用 RSA 密鑰對簽名和驗證簽名。
這是我生成密鑰對的方式(可以很好地用於加密/解密):
ssh-keygen -t rsa -f mykey -N '' -b 2048 mv mykey mykey-priv.pem ssh-keygen -f mykey.pub -e -m pem > mykey-pub.pem ; rm -f mykey.pub
但是,當我嘗試加密雜湊(使用私鑰)然後驗證它(使用公鑰)時,它失敗了:
openssl dgst -sha256 /etc/hosts > /tmp/hash openssl rsautl -sign -inkey mykey-priv.pem -in /tmp/hash -out /tmp/signature openssl rsautl -verify -pubin -inkey mykey-pub.pem -in /tmp/signature
最後一行讓我無法載入公鑰
我錯過了什麼?
如果相關,我正在使用 CentOS 3.9(舊的和舊的,但我在這裡別無選擇)。
最後,這是一個範例密鑰對:
-----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEA8nVhTRuinf4bGAda1ufF+VGG6f8kIFGt8/oCK74n9E6lXgpu 7KqeRzadaiONDh8GgQXn5bX9O2vOL+sL0xYa3W13eCoT7+4U51C/+8HqBxujRAVm i4r/Ju+52kober+GSuIfoNF2nMA24EDy9tid0JgHcBJ0NTyhv6sPvNfcFR1Flbpo LixTGCcn5S9A9NzJXiOkZ6abnxmyEmZsEaboowMay027GLWAw186GODbrGBByhjq W6W6jcijb7EFdIYCEqtC6RsZmAiuPBK0LfW5078GE05oIZrG8GtQR8f7k8HDpEDF +ZI53CZiLhrcXq6+tS4U57FqQs8ytUf6Gno7JwIDAQABAoIBAQCn7zd64gZLqmJ3 zThVG+obGyX4U3lhTVHQaD0ysR4ZcJPHxDA6ip7gsmprxr3/puupWD7b86a3jp8c v4/MIEZxUk3qlDKFAAHIijy/kvuW+sSl65uwUZETFf5DvQq1hYzttxuzFwIx5kzc HQBsi3MbtQGJ1a5Z5WofSMu4wEa289tAjHQiaXs8WEbgOctwS11lhFbDLwLagBFz FL+J0C0oGjgNYaLJUihZKsMHCPZ0/LVFDcCus0ep7mQmvAEQ3FhSNNVakUL07XmM MC6PTUxUvQa8vGDlRnXwGlIWVFNevvudvZjs02J7KWc3hUH9DqXiEm7cClJfoISB HIq4WFvpAoGBAP0UHfCRyv4/2nZmizX05NG/qMNuz97G6Rir2ltw9wmrpvqK/n4r d1JX19ECCx2nQM04C4Q7jQMmyqpF21Wf903PrGXPBa8j5XIDJy+YPC2RrifGsaHm wN1EmYVfYZCphwmTIO2D05n/4Zkgze/KmhMnqpWn27De+LLfgcxsbET7AoGBAPVB 4RvpQCfKdP+ieKRopDE0v+UkdQCogdUz0rhwAdwzhXmUZIJ/Xb4a15DIN+zxKz2h aiIJFkifKw5bQQQQjiIuRN73YpjQ6D9jWTdEs3E1zaWYFNPNAYqSi/1g/udgLL0N RAOw5aNCDyOV4OZRESa9rhUUngfK4VrbqWIm1pLFAoGBAOBGWZn9uaTDNXjDuw6f 7b+rV4WJyBEmuR8x/JoYa/RX9+wEDTAGmQGR8yG3693lgFndFueiVn66e9OVgKBK 2MBOD/tRETp6VzVIcguNn5bKiUmanYRamAP+bQZy1mV6tr7XcdDKiFTrHCO1nIqq QwxClLt3PAtsLX1m8QIV+4TNAoGBAMA161hWi2Mj9mHKUUZ4hAXUU3ggBFqJtYcD 4GeP0MVk03yfYc4sR6mPm9XqNHpL4BmjAWy/Nmmf5LyRo/itiNcc7/jWZL1jLEFR eUApZYCaLBtVfy0nA8g4ZeIkPGHVK/rWBLHn13EFepvnAKVAb3KvQVlgGSH+THNK qAs2aQAJAoGAabSXLpXsZTdy1lMUtZlvUhH4tLVgHFJGILMQ3bh2TTMnkaVbPFyy KDeK+QJGaqjTx1SIXYgANR5cYI1xNge6aVA6T2aY2Dlq3qpAOK3sJWhEZYDxJKeq Oy97h96/n14jdfh1U4TValcZfgVXqAfBMjxx0fPtSQjIn2RVjZRBpFs= -----END RSA PRIVATE KEY----- -----BEGIN RSA PUBLIC KEY----- MIIBCgKCAQEA8nVhTRuinf4bGAda1ufF+VGG6f8kIFGt8/oCK74n9E6lXgpu7Kqe RzadaiONDh8GgQXn5bX9O2vOL+sL0xYa3W13eCoT7+4U51C/+8HqBxujRAVmi4r/ Ju+52kober+GSuIfoNF2nMA24EDy9tid0JgHcBJ0NTyhv6sPvNfcFR1FlbpoLixT GCcn5S9A9NzJXiOkZ6abnxmyEmZsEaboowMay027GLWAw186GODbrGBByhjqW6W6 jcijb7EFdIYCEqtC6RsZmAiuPBK0LfW5078GE05oIZrG8GtQR8f7k8HDpEDF+ZI5 3CZiLhrcXq6+tS4U57FqQs8ytUf6Gno7JwIDAQAB -----END RSA PUBLIC KEY-----
另外:
ssh-keygen -m
僅在相當新的 OpenSSH 版本中,比我在 CentOS 3.9 上預期的要新得多。您是否使用了一些輔助儲存庫或自己建構它或其他什麼?反正…OpenSSH 所稱的“PEM”與此處使用的 PEM OpenSSL 不同。
背景:OpenSSL庫長期以來一直支持 PEM 和 DER 格式的兩種公鑰結構:
- 特定於每個支持的算法的“傳統”結構,PEM 標頭類似於
-----BEGIN RSA PUBLIC KEY-----
-----BEGIN DSA PUBLIC KEY-----
-----BEGIN EC PUBLIC KEY-----
常式實現
PEM_{write,read}{RSA,DSA,EC}PublicKey
- 一種由 X.509 定義的通用結構,以
SubjectPublicKeyInfo
PEM 標頭命名
-----BEGIN PUBLIC KEY-----
!注意常式沒有實現算法名稱
PEM_{write,read}{,RSA,DSA,EC}PUBKEY
然而,OpenSSL命令行幾乎只使用後者,包括 for
rsautl -pubin
. 你可以看到你有前者。為什麼?OpenSSH最近添加了導出
-m
格式選項時ssh-keygen -e
,莫名其妙地將 OpenSSL 傳統結構命名為PEM
OpenSSL X.509 通用結構PKCS8
——儘管它根本不是 PKCS#8,它是私鑰的標準和通用格式。所以你的選擇是:
- 使用看起來錯誤但實際上正確的格式選項
ssh-keygen -e -m pkcs8
- 使用處理遺留結構的唯一操作轉換您擁有的文件:但
openssl rsa -in sshpub_called_pem -RSAPublicKey_in -out goodpub -pubout
僅限於 OpenSSL 1.0.0 及更高版本。
- 鑑於您的 OpenSSH 私鑰文件是與 OpenSSL 兼容的格式(
-----BEGIN RSA PRIVATE KEY-----
這-----BEGIN OPENSSH PRIVATE KEY-----
也是 OpenSSH 的最新添加),您可以使用 OpenSSL而不是ssh-keygen -e
:
openssl rsa -in sshprivate -pubout -out pubforopenssl
或在 1.0.0 及更高版本中,閃亮的新替代品
openssl pkey -in sshprivate -pubout -out pubforopenssl
另請注意:(
rsautl -sign|-verify
預設情況下)使用 PKCS#1-v1.5(又名 01 型)填充,但不遵守要求您還對 ASN.1 中的散列進行編碼的標準SEQUENCE
。您以這種方式創建的簽名不會在符合標準的其他軟體中驗證,並且在其他軟體中創建的簽名會給出不同的(儘管部分匹配)結果。考慮改為使用openssl {dgst -hashname | hashname} {-sign privatekey | -verify publickey}
它執行完整的操作:散列數據、ASN.1 編碼、填充和 RSA 簽名,或者相反的 RSA 驗證、取消填充、解碼和匹配;或者
openssl pkeyutl -sign|-verify -inkey key [-pubin] -pkeyopt digest:hashname
其中密鑰是一個 RSA 密鑰,它執行所有 PKCS#1-v1.5,除了散列數據。例如:
https://stackoverflow.com/questions/9951559/difference-between-openssl-rsautl-and-dgst
https://crypto.stackexchange.com/questions/27892/verify-a -rsa-signature-using-only-rsa-encryption