You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
3.0 KiB

  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. // Package tea implements the TEA algorithm, as defined in Needham and
  5. // Wheeler's 1994 technical report, “TEA, a Tiny Encryption Algorithm”. See
  6. // http://www.cix.co.uk/~klockstone/tea.pdf for details.
  7. package tea
  8. import (
  9. "crypto/cipher"
  10. "encoding/binary"
  11. "errors"
  12. )
  13. const (
  14. // BlockSize is the size of a TEA block, in bytes.
  15. BlockSize = 8
  16. // KeySize is the size of a TEA key, in bytes.
  17. KeySize = 16
  18. // delta is the TEA key schedule constant.
  19. delta = 0x9e3779b9
  20. // numRounds is the standard number of rounds in TEA.
  21. numRounds = 64
  22. )
  23. // tea is an instance of the TEA cipher with a particular key.
  24. type tea struct {
  25. key [16]byte
  26. rounds int
  27. }
  28. // NewCipher returns an instance of the TEA cipher with the standard number of
  29. // rounds. The key argument must be 16 bytes long.
  30. func NewCipher(key []byte) (cipher.Block, error) {
  31. return NewCipherWithRounds(key, numRounds)
  32. }
  33. // NewCipherWithRounds returns an instance of the TEA cipher with a given
  34. // number of rounds, which must be even. The key argument must be 16 bytes
  35. // long.
  36. func NewCipherWithRounds(key []byte, rounds int) (cipher.Block, error) {
  37. if len(key) != 16 {
  38. return nil, errors.New("tea: incorrect key size")
  39. }
  40. if rounds&1 != 0 {
  41. return nil, errors.New("tea: odd number of rounds specified")
  42. }
  43. c := &tea{
  44. rounds: rounds,
  45. }
  46. copy(c.key[:], key)
  47. return c, nil
  48. }
  49. // BlockSize returns the TEA block size, which is eight bytes. It is necessary
  50. // to satisfy the Block interface in the package "crypto/cipher".
  51. func (*tea) BlockSize() int {
  52. return BlockSize
  53. }
  54. // Encrypt encrypts the 8 byte buffer src using the key in t and stores the
  55. // result in dst. Note that for amounts of data larger than a block, it is not
  56. // safe to just call Encrypt on successive blocks; instead, use an encryption
  57. // mode like CBC (see crypto/cipher/cbc.go).
  58. func (t *tea) Encrypt(dst, src []byte) {
  59. e := binary.BigEndian
  60. v0, v1 := e.Uint32(src), e.Uint32(src[4:])
  61. k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:])
  62. sum := uint32(0)
  63. delta := uint32(delta)
  64. for i := 0; i < t.rounds/2; i++ {
  65. sum += delta
  66. v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1)
  67. v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3)
  68. }
  69. e.PutUint32(dst, v0)
  70. e.PutUint32(dst[4:], v1)
  71. }
  72. // Decrypt decrypts the 8 byte buffer src using the key in t and stores the
  73. // result in dst.
  74. func (t *tea) Decrypt(dst, src []byte) {
  75. e := binary.BigEndian
  76. v0, v1 := e.Uint32(src), e.Uint32(src[4:])
  77. k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:])
  78. delta := uint32(delta)
  79. sum := delta * uint32(t.rounds/2) // in general, sum = delta * n
  80. for i := 0; i < t.rounds/2; i++ {
  81. v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3)
  82. v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1)
  83. sum -= delta
  84. }
  85. e.PutUint32(dst, v0)
  86. e.PutUint32(dst[4:], v1)
  87. }