libsodium 流加密
我是密碼學新手,我之前使用過 OpenSSL 及其
aes-256-cfb
密碼來進行流加密,效果很好。現在我要試試了libsodium
,因為它很輕,而且它的 API 看起來很簡潔,但我無法讓它工作。我嘗試了它的
XChaCha20
流密碼,但它只有crypto_stream_xchacha20_xor
和crypto_stream_xchacha20_xor_ic
功能,當消息長度成對出現時,我可以輕鬆地加密和解密消息,比如加密 20 個字節,然後解密 20 個字節,這很好用。但如果加密 20 個字節,然後解密 10 個字節並再解密 10 個字節,它將失敗。後一種情況是我想要的,我正在實現一個代理,我想從一個 TCP 連接讀取數據的隨機長度(即不是塊和無邊界),通過另一個 TCP 連接加密和流式傳輸數據,另一端連接讀取加密數據的隨機長度並對其進行解密。對於我想要的,
xor
我的數據不起作用,因為沒有context
像 OpenSSL 這樣的對象,也EVP_CIPHER_CTX
沒有保存多少字節被加密/解密的資訊,如果它不支持這種流,這對我來說很奇怪模式,為什麼叫流密碼?我的問題:是否可以使用 libsodium 做我想做的事,如果可以,怎麼做?
libsodium 有一個專用於流加密的 API:
crypto_secretstream
,這裡有完整的文件:https://download.libsodium.org/doc/secret-key_cryptography/secretstream.html簡單地使用
crypto_stream_*
或使用 OpenSSLaes-256-cfb
將是完全不安全的。如果沒有任何身份驗證標籤,則可以篡改流,而沒有任何方法可以檢測到它發生了。
crypto_secretstream
允許您加密和解密一系列可變長度的消息,並防止篡改、重新排序和截斷。但是,如果 50 字節,則 20 字節被加密,您必須依次解密 50 字節和 20 字節。
如果您正在從 TCP 連接讀取數據,則可以將其累積到一個固定大小的緩衝區中,一旦該緩衝區已滿或您已到達流的末尾,就可以加密或解密其內容。這也將提高性能並最大限度地減少身份驗證標籤的成本,而不是加密單個
read()
呼叫的結果。如果會話是互動式的,您的選擇是:
- 在加密之前將消息填充到塊大小 (
sodium_pad()
, )。sodium_unpad()
這會使用更多頻寬,但會通過顯示更少的消息大小資訊來提高安全性。- 為每個密文加上其大小的前綴,這樣您就知道在解密之前必須讀取多少數據。