Source file src/crypto/rc4/rc4.go

     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/alias"
    14  	"strconv"
    15  )
    16  
    17  // A Cipher is an instance of RC4 using a particular key.
    18  type Cipher struct {
    19  	s    [256]uint32
    20  	i, j uint8
    21  }
    22  
    23  type KeySizeError int
    24  
    25  func (k KeySizeError) Error() string {
    26  	return "crypto/rc4: invalid key size " + strconv.Itoa(int(k))
    27  }
    28  
    29  // NewCipher creates and returns a new [Cipher]. The key argument should be the
    30  // RC4 key, at least 1 byte and at most 256 bytes.
    31  func NewCipher(key []byte) (*Cipher, error) {
    32  	k := len(key)
    33  	if k < 1 || k > 256 {
    34  		return nil, KeySizeError(k)
    35  	}
    36  	var c Cipher
    37  	for i := 0; i < 256; i++ {
    38  		c.s[i] = uint32(i)
    39  	}
    40  	var j uint8 = 0
    41  	for i := 0; i < 256; i++ {
    42  		j += uint8(c.s[i]) + key[i%k]
    43  		c.s[i], c.s[j] = c.s[j], c.s[i]
    44  	}
    45  	return &c, nil
    46  }
    47  
    48  // Reset zeros the key data and makes the [Cipher] unusable.
    49  //
    50  // Deprecated: Reset can't guarantee that the key will be entirely removed from
    51  // the process's memory.
    52  func (c *Cipher) Reset() {
    53  	for i := range c.s {
    54  		c.s[i] = 0
    55  	}
    56  	c.i, c.j = 0, 0
    57  }
    58  
    59  // XORKeyStream sets dst to the result of XORing src with the key stream.
    60  // Dst and src must overlap entirely or not at all.
    61  func (c *Cipher) XORKeyStream(dst, src []byte) {
    62  	if len(src) == 0 {
    63  		return
    64  	}
    65  	if alias.InexactOverlap(dst[:len(src)], src) {
    66  		panic("crypto/rc4: invalid buffer overlap")
    67  	}
    68  	i, j := c.i, c.j
    69  	_ = dst[len(src)-1]
    70  	dst = dst[:len(src)] // eliminate bounds check from loop
    71  	for k, v := range src {
    72  		i += 1
    73  		x := c.s[i]
    74  		j += uint8(x)
    75  		y := c.s[j]
    76  		c.s[i], c.s[j] = y, x
    77  		dst[k] = v ^ uint8(c.s[uint8(x+y)])
    78  	}
    79  	c.i, c.j = i, j
    80  }
    81  

View as plain text