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/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  

View as plain text