Encryption

libsodium 流加密

  • December 12, 2019

我是密碼學新手,我之前使用過 OpenSSL 及其aes-256-cfb密碼來進行流加密,效果很好。現在我要試試了libsodium,因為它很輕,而且它的 API 看起來很簡潔,但我無法讓它工作。

我嘗試了它的XChaCha20流密碼,但它只有crypto_stream_xchacha20_xorcrypto_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()這會使用更多頻寬,但會通過顯示更少的消息大小資訊來提高安全性。
  • 為每個密文加上其大小的前綴,這樣您就知道在解密之前必須讀取多少數據。

引用自:https://crypto.stackexchange.com/questions/61275