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.Enforced() {
    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  	clear(c.s[:])
    59  	c.i, c.j = 0, 0
    60  }
    61  
    62  // XORKeyStream sets dst to the result of XORing src with the key stream.
    63  // Dst and src must overlap entirely or not at all.
    64  func (c *Cipher) XORKeyStream(dst, src []byte) {
    65  	if len(src) == 0 {
    66  		return
    67  	}
    68  	if alias.InexactOverlap(dst[:len(src)], src) {
    69  		panic("crypto/rc4: invalid buffer overlap")
    70  	}
    71  	i, j := c.i, c.j
    72  	_ = dst[len(src)-1]
    73  	dst = dst[:len(src)] // eliminate bounds check from loop
    74  	for k, v := range src {
    75  		i += 1
    76  		x := c.s[i]
    77  		j += uint8(x)
    78  		y := c.s[j]
    79  		c.s[i], c.s[j] = y, x
    80  		dst[k] = v ^ uint8(c.s[uint8(x+y)])
    81  	}
    82  	c.i, c.j = i, j
    83  }
    84  

View as plain text