Home | History | Annotate | Download | only in rc4
      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 package rc4
      8 
      9 // BUG(agl): RC4 is in common use but has design weaknesses that make
     10 // it a poor choice for new protocols.
     11 
     12 import "strconv"
     13 
     14 // A Cipher is an instance of RC4 using a particular key.
     15 type Cipher struct {
     16 	s    [256]uint32
     17 	i, j uint8
     18 }
     19 
     20 type KeySizeError int
     21 
     22 func (k KeySizeError) Error() string {
     23 	return "crypto/rc4: invalid key size " + strconv.Itoa(int(k))
     24 }
     25 
     26 // NewCipher creates and returns a new Cipher. The key argument should be the
     27 // RC4 key, at least 1 byte and at most 256 bytes.
     28 func NewCipher(key []byte) (*Cipher, error) {
     29 	k := len(key)
     30 	if k < 1 || k > 256 {
     31 		return nil, KeySizeError(k)
     32 	}
     33 	var c Cipher
     34 	for i := 0; i < 256; i++ {
     35 		c.s[i] = uint32(i)
     36 	}
     37 	var j uint8 = 0
     38 	for i := 0; i < 256; i++ {
     39 		j += uint8(c.s[i]) + key[i%k]
     40 		c.s[i], c.s[j] = c.s[j], c.s[i]
     41 	}
     42 	return &c, nil
     43 }
     44 
     45 // Reset zeros the key data so that it will no longer appear in the
     46 // process's memory.
     47 func (c *Cipher) Reset() {
     48 	for i := range c.s {
     49 		c.s[i] = 0
     50 	}
     51 	c.i, c.j = 0, 0
     52 }
     53 
     54 // xorKeyStreamGeneric sets dst to the result of XORing src with the
     55 // key stream. Dst and src may be the same slice but otherwise should
     56 // not overlap.
     57 //
     58 // This is the pure Go version. rc4_{amd64,386,arm}* contain assembly
     59 // implementations. This is here for tests and to prevent bitrot.
     60 func (c *Cipher) xorKeyStreamGeneric(dst, src []byte) {
     61 	i, j := c.i, c.j
     62 	for k, v := range src {
     63 		i += 1
     64 		j += uint8(c.s[i])
     65 		c.s[i], c.s[j] = c.s[j], c.s[i]
     66 		dst[k] = v ^ uint8(c.s[uint8(c.s[i]+c.s[j])])
     67 	}
     68 	c.i, c.j = i, j
     69 }
     70