...

Source file src/golang.org/x/crypto/tea/cipher.go

Documentation: golang.org/x/crypto/tea

     1  // Copyright 2015 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 tea implements the TEA algorithm, as defined in Needham and
     6  // Wheeler's 1994 technical report, “TEA, a Tiny Encryption Algorithm”. See
     7  // http://www.cix.co.uk/~klockstone/tea.pdf for details.
     8  //
     9  // TEA is a legacy cipher and its short block size makes it vulnerable to
    10  // birthday bound attacks (see https://sweet32.info). It should only be used
    11  // where compatibility with legacy systems, not security, is the goal.
    12  //
    13  // Deprecated: any new system should use AES (from crypto/aes, if necessary in
    14  // an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from
    15  // golang.org/x/crypto/chacha20poly1305).
    16  package tea
    17  
    18  import (
    19  	"crypto/cipher"
    20  	"encoding/binary"
    21  	"errors"
    22  )
    23  
    24  const (
    25  	// BlockSize is the size of a TEA block, in bytes.
    26  	BlockSize = 8
    27  
    28  	// KeySize is the size of a TEA key, in bytes.
    29  	KeySize = 16
    30  
    31  	// delta is the TEA key schedule constant.
    32  	delta = 0x9e3779b9
    33  
    34  	// numRounds is the standard number of rounds in TEA.
    35  	numRounds = 64
    36  )
    37  
    38  // tea is an instance of the TEA cipher with a particular key.
    39  type tea struct {
    40  	key    [16]byte
    41  	rounds int
    42  }
    43  
    44  // NewCipher returns an instance of the TEA cipher with the standard number of
    45  // rounds. The key argument must be 16 bytes long.
    46  func NewCipher(key []byte) (cipher.Block, error) {
    47  	return NewCipherWithRounds(key, numRounds)
    48  }
    49  
    50  // NewCipherWithRounds returns an instance of the TEA cipher with a given
    51  // number of rounds, which must be even. The key argument must be 16 bytes
    52  // long.
    53  func NewCipherWithRounds(key []byte, rounds int) (cipher.Block, error) {
    54  	if len(key) != 16 {
    55  		return nil, errors.New("tea: incorrect key size")
    56  	}
    57  
    58  	if rounds&1 != 0 {
    59  		return nil, errors.New("tea: odd number of rounds specified")
    60  	}
    61  
    62  	c := &tea{
    63  		rounds: rounds,
    64  	}
    65  	copy(c.key[:], key)
    66  
    67  	return c, nil
    68  }
    69  
    70  // BlockSize returns the TEA block size, which is eight bytes. It is necessary
    71  // to satisfy the Block interface in the package "crypto/cipher".
    72  func (*tea) BlockSize() int {
    73  	return BlockSize
    74  }
    75  
    76  // Encrypt encrypts the 8 byte buffer src using the key in t and stores the
    77  // result in dst. Note that for amounts of data larger than a block, it is not
    78  // safe to just call Encrypt on successive blocks; instead, use an encryption
    79  // mode like CBC (see crypto/cipher/cbc.go).
    80  func (t *tea) Encrypt(dst, src []byte) {
    81  	e := binary.BigEndian
    82  	v0, v1 := e.Uint32(src), e.Uint32(src[4:])
    83  	k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:])
    84  
    85  	sum := uint32(0)
    86  	delta := uint32(delta)
    87  
    88  	for i := 0; i < t.rounds/2; i++ {
    89  		sum += delta
    90  		v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1)
    91  		v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3)
    92  	}
    93  
    94  	e.PutUint32(dst, v0)
    95  	e.PutUint32(dst[4:], v1)
    96  }
    97  
    98  // Decrypt decrypts the 8 byte buffer src using the key in t and stores the
    99  // result in dst.
   100  func (t *tea) Decrypt(dst, src []byte) {
   101  	e := binary.BigEndian
   102  	v0, v1 := e.Uint32(src), e.Uint32(src[4:])
   103  	k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:])
   104  
   105  	delta := uint32(delta)
   106  	sum := delta * uint32(t.rounds/2) // in general, sum = delta * n
   107  
   108  	for i := 0; i < t.rounds/2; i++ {
   109  		v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3)
   110  		v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1)
   111  		sum -= delta
   112  	}
   113  
   114  	e.PutUint32(dst, v0)
   115  	e.PutUint32(dst[4:], v1)
   116  }
   117  

View as plain text