1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 5 // Package rc4 implements RC4 encryption, as defined in Bruce Schneier's
6 // Applied Cryptography.
7 //
8 // RC4 is cryptographically broken and should not be used for secure
9 // applications.
10 package rc4
11 12 import (
13 "crypto/internal/fips140/alias"
14 "crypto/internal/fips140only"
15 "errors"
16 "strconv"
17 )
18 19 // A Cipher is an instance of RC4 using a particular key.
20 type Cipher struct {
21 s [256]uint32
22 i, j uint8
23 }
24 25 type KeySizeError int
26 27 func (k KeySizeError) Error() string {
28 return "crypto/rc4: invalid key size " + strconv.Itoa(int(k))
29 }
30 31 // NewCipher creates and returns a new [Cipher]. The key argument should be the
32 // RC4 key, at least 1 byte and at most 256 bytes.
33 func NewCipher(key []byte) (*Cipher, error) {
34 if fips140only.Enabled {
35 return nil, errors.New("crypto/rc4: use of RC4 is not allowed in FIPS 140-only mode")
36 }
37 k := len(key)
38 if k < 1 || k > 256 {
39 return nil, KeySizeError(k)
40 }
41 var c Cipher
42 for i := 0; i < 256; i++ {
43 c.s[i] = uint32(i)
44 }
45 var j uint8 = 0
46 for i := 0; i < 256; i++ {
47 j += uint8(c.s[i]) + key[i%k]
48 c.s[i], c.s[j] = c.s[j], c.s[i]
49 }
50 return &c, nil
51 }
52 53 // Reset zeros the key data and makes the [Cipher] unusable.
54 //
55 // Deprecated: Reset can't guarantee that the key will be entirely removed from
56 // the process's memory.
57 func (c *Cipher) Reset() {
58 for i := range c.s {
59 c.s[i] = 0
60 }
61 c.i, c.j = 0, 0
62 }
63 64 // XORKeyStream sets dst to the result of XORing src with the key stream.
65 // Dst and src must overlap entirely or not at all.
66 func (c *Cipher) XORKeyStream(dst, src []byte) {
67 if len(src) == 0 {
68 return
69 }
70 if alias.InexactOverlap(dst[:len(src)], src) {
71 panic("crypto/rc4: invalid buffer overlap")
72 }
73 i, j := c.i, c.j
74 _ = dst[len(src)-1]
75 dst = dst[:len(src)] // eliminate bounds check from loop
76 for k, v := range src {
77 i += 1
78 x := c.s[i]
79 j += uint8(x)
80 y := c.s[j]
81 c.s[i], c.s[j] = y, x
82 dst[k] = v ^ uint8(c.s[uint8(x+y)])
83 }
84 c.i, c.j = i, j
85 }
86