v / vlib / crypto / rc4 / rc4.v
90 lines · 84 sloc · 2.06 KB · d15f06444febe8320403cc0822f254cc34c2ca7f
Raw
1module rc4
2
3// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
4// Use of this source code is governed by an MIT license
5// that can be found in the LICENSE file.
6// Package rc4 implements RC4 encryption, as defined in Bruce Schneier's
7// Applied Cryptography.
8//
9// RC4 is cryptographically broken and should not be used for secure
10// applications.
11// Based off: https://github.com/golang/go/blob/master/src/crypto/rc4
12// Last commit: https://github.com/golang/go/commit/b35dacaac57b039205d9b07ea24098e2c3fcb12e
13import crypto.internal.subtle
14
15// A Cipher is an instance of RC4 using a particular key.
16struct Cipher {
17mut:
18 s []u32
19 i u8
20 j u8
21}
22
23// free the resources taken by the Cipher `c`
24@[unsafe]
25pub fn (mut c Cipher) free() {
26 $if prealloc {
27 return
28 }
29 unsafe { c.s.free() }
30}
31
32// new_cipher creates and returns a new Cipher. The key argument should be the
33// RC4 key, at least 1 byte and at most 256 bytes.
34@[direct_array_access]
35pub fn new_cipher(key []u8) !&Cipher {
36 if key.len < 1 || key.len > 256 {
37 return error('crypto.rc4: invalid key size ' + key.len.str())
38 }
39 mut c := &Cipher{
40 s: []u32{len: (256)}
41 }
42 for i in 0 .. 256 {
43 c.s[i] = u32(i)
44 }
45 mut j := u8(0)
46 for i in 0 .. 256 {
47 j += u8(c.s[i]) + key[i % key.len]
48 tmp := c.s[i]
49 c.s[i] = c.s[j]
50 c.s[j] = tmp
51 }
52 return c
53}
54
55// reset zeros the key data and makes the Cipher unusable.good to com
56//
57// Deprecated: Reset can't guarantee that the key will be entirely removed from
58// the process's memory.
59pub fn (mut c Cipher) reset() {
60 for i in c.s {
61 c.s[i] = 0
62 }
63 c.i = 0
64 c.j = 0
65}
66
67// xor_key_stream sets dst to the result of XORing src with the key stream.
68// Dst and src must overlap entirely or not at all.
69@[direct_array_access]
70pub fn (mut c Cipher) xor_key_stream(mut dst []u8, src []u8) {
71 if src.len == 0 {
72 return
73 }
74 if subtle.inexact_overlap(dst, src) {
75 panic('crypto.rc4: invalid buffer overlap')
76 }
77 mut i := c.i
78 mut j := c.j
79 for k, v in src {
80 i += u8(1)
81 x := c.s[i]
82 j += u8(x)
83 y := c.s[j]
84 c.s[i] = y
85 c.s[j] = x
86 dst[k] = v ^ u8(c.s[u8(x + y)])
87 }
88 c.i = i
89 c.j = j
90}
91