github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/crypto/tea/cipher.go (about) 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 package tea 10 11 import ( 12 "crypto/cipher" 13 "encoding/binary" 14 "errors" 15 ) 16 17 const ( 18 // BlockSize is the size of a TEA block, in bytes. 19 BlockSize = 8 20 21 // KeySize is the size of a TEA key, in bytes. 22 KeySize = 16 23 24 // delta is the TEA key schedule constant. 25 delta = 0x9e3779b9 26 27 // numRounds is the standard number of rounds in TEA. 28 numRounds = 64 29 ) 30 31 // tea is an instance of the TEA cipher with a particular key. 32 type tea struct { 33 key [16]byte 34 rounds int 35 } 36 37 // NewCipher returns an instance of the TEA cipher with the standard number of 38 // rounds. The key argument must be 16 bytes long. 39 func NewCipher(key []byte) (cipher.Block, error) { 40 return NewCipherWithRounds(key, numRounds) 41 } 42 43 // NewCipherWithRounds returns an instance of the TEA cipher with a given 44 // number of rounds, which must be even. The key argument must be 16 bytes 45 // long. 46 func NewCipherWithRounds(key []byte, rounds int) (cipher.Block, error) { 47 if len(key) != 16 { 48 return nil, errors.New("tea: incorrect key size") 49 } 50 51 if rounds&1 != 0 { 52 return nil, errors.New("tea: odd number of rounds specified") 53 } 54 55 c := &tea{ 56 rounds: rounds, 57 } 58 copy(c.key[:], key) 59 60 return c, nil 61 } 62 63 // BlockSize returns the TEA block size, which is eight bytes. It is necessary 64 // to satisfy the Block interface in the package "crypto/cipher". 65 func (*tea) BlockSize() int { 66 return BlockSize 67 } 68 69 // Encrypt encrypts the 8 byte buffer src using the key in t and stores the 70 // result in dst. Note that for amounts of data larger than a block, it is not 71 // safe to just call Encrypt on successive blocks; instead, use an encryption 72 // mode like CBC (see crypto/cipher/cbc.go). 73 func (t *tea) Encrypt(dst, src []byte) { 74 e := binary.BigEndian 75 v0, v1 := e.Uint32(src), e.Uint32(src[4:]) 76 k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:]) 77 78 sum := uint32(0) 79 delta := uint32(delta) 80 81 for i := 0; i < t.rounds/2; i++ { 82 sum += delta 83 v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) 84 v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) 85 } 86 87 e.PutUint32(dst, v0) 88 e.PutUint32(dst[4:], v1) 89 } 90 91 // Decrypt decrypts the 8 byte buffer src using the key in t and stores the 92 // result in dst. 93 func (t *tea) Decrypt(dst, src []byte) { 94 e := binary.BigEndian 95 v0, v1 := e.Uint32(src), e.Uint32(src[4:]) 96 k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:]) 97 98 delta := uint32(delta) 99 sum := delta * uint32(t.rounds/2) // in general, sum = delta * n 100 101 for i := 0; i < t.rounds/2; i++ { 102 v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) 103 v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) 104 sum -= delta 105 } 106 107 e.PutUint32(dst, v0) 108 e.PutUint32(dst[4:], v1) 109 }