使用 OpenSSL 實現經過身份驗證的加密的最佳方法是什麼?
問題
我想通過不受信任的連結在我自己和其他人之間發送純文字文件。我想首先阻止第三方閱讀文件,我希望接收者能夠驗證他們收到的任何消息來自我。最後,我希望接收者能夠閱讀文件。我有能力通過受信任的渠道向接收者提供密鑰。
建議的解決方案
文件使用對稱密碼加密。我打算使用的 aes-key 可以變成簽名。例如
openssl pkeyutl -sign -in "aes.key" -inkey privkey.pem -out sig.nature
此簽名不用於身份驗證(使用基於加密文件雜湊的單獨簽名),但它似乎隱藏了密鑰的值,然後可以使用公鑰提取該值。例如
openssl rsautl -verify -inkey pubkey.pem -in sig.nature -pubin >> aeskey.recov
公鑰不會公開,但會通過受信任的渠道提供給接收者並得到保護。但是,我知道如果公鑰被洩露,那麼我所有的加密文件都可以被解密。
這是有效的(假設公鑰仍然是私有的)還是有更好的方法來做到這一點?
如果你說你
有能力通過受信任的渠道向接收者提供密鑰。
那麼這裡不需要涉及任何公鑰加密。只需生成一個對稱密鑰,然後通過可信渠道將該密鑰發送給您的朋友。
稍後,一旦您準備好發送文件,只需使用經過身份驗證的加密模式對文件進行加密,然後將加密後的文件發送給您的朋友。然後他們可以使用他們的密鑰來驗證密文的真實性並解密。
您是說您特別想知道如何使用 OpenSSL 命令行工具來做到這一點。這有點離題了,但我們還是開始了。
免責聲明:不要在任何實際應用程序中使用我在下面寫的任何內容,我不聲稱下面描述的使用 openssl 在實踐中實際上是安全的。
注意,我將在下面使用 bash 語法,我不知道它是否適用於其他 shell。
我們需要做的第一件事是生成密鑰。我們將使用 AES-128,因此我們將生成 16 個隨機字節並將它們儲存在密鑰文件中。(編碼為十六進制以使我們以後的生活更輕鬆。)
openssl rand -hex 16 > enc.key
我們還將生成一個單獨的 MAC 密鑰,我將在稍後解釋原因:
openssl rand -hex 16 > mac.key
這兩個文件你將給你的朋友。
第一個想法 - 因為我們想要一個經過身份驗證的加密模式 - 將使用像 AES-GCM 這樣的東西,但遺憾的是,命令行工具
openssl enc
會告訴我們enc 實用程序不支持 AEAD 密碼
無賴!作者不願意改變這一點。 因此,我們將不得不以艱難的方式進行身份驗證。例如使用 AES-CTR + HMAC。這就是為什麼我們之前創建了一個單獨的 MAC 密鑰。
並且因為 OpenSSL 的作者真的希望您自取其辱:如果您實際上指定了一個密鑰,那麼該
openssl enc
實用程序不會為我們創建一個 IV,因此我們也必須自己這樣做。所以讓我們開始吧。我們生成一個初始化向量openssl rand -hex 16 > file.iv
然後
file.txt
使用生成的 IV 和我們之前交換的密鑰使用 AES-CTR 加密我們的文件。openssl enc -aes-128-ctr -in file.txt -out file.aes -K $(cat enc.key) -iv $(cat file.iv)
在 IV 和密文上計算 HMAC
cat file.iv file.aes | openssl dgst -mac HMAC -macopt hexkey:$(cat mac.key) -out file.mac
現在您可以發送
file.iv
,file.aes
,file.mac
給您的朋友。話又說回來,因為 OpenSSL 的作者真的,真的想讓你在腳下開槍,這個
openssl dgst
實用程序自然不支持驗證。相反,您的朋友將不得不手動進行驗證:if [ "$(cat file.iv file.aes | openssl dgst -mac HMAC -macopt hexkey:$(cat mac.key))" == "$(cat file.mac)" ]; then echo "MAC verification succesful." openssl enc -d -aes-128-ctr -in file.aes -out file.txt -K $(cat enc.key) -iv $(cat file.iv); else echo "MAC verification failed." fi
如果一切順利,他們現在應該可以恢復明文。
到現在為止,我希望每個讀者都已經意識到在所有這一切中可能出錯的地方太多了,並決定不手動進行加密文件傳輸。