撰寫一個串流轉接器,其中包含一個金鑰的參照,並將它與任意資料做位元 XOR 運算。
XOR 是一種基本的二元運算:對輸入中的每個位元,如果兩個輸入位元不同,就把輸出的對應位元設為 1。如果兩個輸入都是 1,或兩個都是 0,那麼對應的輸出位元就是 0。
用金鑰對文件做 XOR 時,金鑰會視需要重複任意次數,產生的輸出文件長度與輸入文件相同。
用金鑰對文件做 XOR 的作法,直到 1900 年代初期都還被用於密碼學。雖然這種隱藏資料的方法早已完全過時,但它在產生看似隨機的雜訊資料時意外地好用,又不必處理真正隨機性帶來的麻煩。在現代密碼學中,它偶爾仍會用於某些加密法:加密法本身只是一種機制,用來產生非常隨機、無限長的金鑰,再與文件做 XOR。
XOR 加密有個有趣的特性:它是對稱的。任何數字與自己做 XOR 都會產生 0,而任何數字與 0 做 XOR 則會原封不動地回傳該輸入數字。因此,要解密一份經過 XOR 加密的文件,只要用同一把金鑰再加密一次即可。
要寫出一個測試來確保你的 struct 持有金鑰的參照,而不是複製它,並不實際。同樣地,也很難用測試證明munge與munge_in_place,以及它們的任何輔助函式,都沒有在堆積上配置記憶體。儘管如此,你還是應該試著用這種方式來寫你的解法。
你需要撰寫一個struct Xorcism,它會持有一個金鑰的參照。這個 struct 必須提供兩個方法:munge_in_place和munge。前者會原地調整一個位元組緩衝區。後者則是一個疊代器轉接器:它接受任意資料的疊代器,並回傳一個新的資料疊代器。
這個練習預留的函式簽名在語法上大致正確,但無法編譯:這個練習的重點有很大一部分是要讓你熟悉生命週期與泛型的使用,所以你需要自己把它們補上。這個練習的另一個目標,是讓你找出適當的拆分方式,盡可能不重複費力就能實作這兩個方法。別害怕加入額外的輔助函式喔!
這些 trait 會很有用:
這個練習包含加分測試,放在io功能旗標後面。若要啟用它們,請執行
cargo test --features io
這些測試需要你實作一個方法reader,其簽名為
fn reader(self, impl Read) -> impl Read
以及一個方法writer,其簽名為
fn writer(self, impl Write) -> impl Write
這些函式會各自把Xorcism這個 struct 轉換成對應方向的串流轉接器。它們會用到這些 trait:
munge 回傳值的生命週期由於使用了impl Trait這項功能,在實作munge方法時,生命週期的管理可能會有點棘手。至少在起步階段,你可能會發現自己寫一個含有Iterator實作的struct,並回傳那個具體型別,會比較容易。到頭來,不妨試著直接用Iterator的組合器來實作解法。