module std::crypto::rc4; // Copyright (c) 2021 Christoffer Lerno. All rights reserved. // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. struct Rc4 { uint i, j; char[256] state; } <* Initialize the RC4 state. @param [in] key "The key to use" @require key.len > 0 "The key must be at least 1 byte long" *> fn void Rc4.init(&self, char[] key) { // Init the state matrix foreach (char i, &c : self.state) *c = i; for (int i = 0, int j = 0; i < 256; i++) { j = (j + self.state[i] + key[i % key.len]) & 0xFF; @swap(self.state[i], self.state[j]); } self.i = 0; self.j = 0; } <* Run a single pass of en/decryption using a particular key. @param [in] key @param [inout] data *> fn void crypt(char[] key, char[] data) { Rc4 rc4; rc4.init(key); rc4.crypt(data, data); } <* Encrypt or decrypt a sequence of bytes. @param [in] in "The input" @param [out] out "The output" @require in.len <= out.len "Output would overflow" *> fn void Rc4.crypt(&self, char[] in, char[] out) { uint i = self.i; uint j = self.j; char* state = &self.state; isz len = in.len; foreach (idx, c : in) { i = (i + 1) & 0xFF; j = (j + state[i]) & 0xFF; @swap(state[i], state[j]); out[idx] = in[idx] ^ state[(state[i] + state[j]) & 0xFF]; } self.i = i; self.j = j; } <* Clear the rc4 state. @param [&out] self "The RC4 State" *> fn void Rc4.destroy(&self) { *self = {}; }