encrypter.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package fte
  2. import (
  3. "crypto/aes"
  4. "crypto/cipher"
  5. "crypto/hmac"
  6. "crypto/rand"
  7. "crypto/sha512"
  8. "encoding/binary"
  9. "errors"
  10. "io"
  11. "math"
  12. "github.com/redjack/marionette/ecb"
  13. )
  14. // _MAC_LENGTH = AES.block_size
  15. // _IV_LENGTH = 7
  16. // _MSG_COUNTER_LENGTH = 8
  17. // _CTXT_EXPANSION = 1 + _IV_LENGTH + _MSG_COUNTER_LENGTH + _MAC_LENGTH
  18. var (
  19. ErrShortCiphertext = errors.New("fte: short ciphertext")
  20. ErrInvalidMessageLength = errors.New("fte: invalid message length")
  21. ErrHMACVerificationFailed = errors.New("fte: hmac verification failed")
  22. )
  23. var (
  24. K1 = []byte("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff")
  25. K2 = []byte("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
  26. )
  27. const _IV_LENGTH = 7
  28. type Encrypter struct {
  29. block cipher.Block
  30. blockMode cipher.BlockMode
  31. IV []byte
  32. }
  33. func NewEncrypter() (*Encrypter, error) {
  34. blk, err := aes.NewCipher(K1)
  35. if err != nil {
  36. return nil, err
  37. }
  38. return &Encrypter{
  39. block: blk,
  40. blockMode: ecb.NewEncrypter(blk),
  41. }, nil
  42. }
  43. func (enc *Encrypter) Encrypt(plaintext []byte) ([]byte, error) {
  44. plaintextN := len(plaintext)
  45. // Read random bytes for initialization vector.
  46. iv := make([]byte, _IV_LENGTH)
  47. if len(enc.IV) == _IV_LENGTH {
  48. copy(iv, enc.IV)
  49. } else {
  50. if _, err := io.ReadFull(rand.Reader, iv); err != nil {
  51. return nil, err
  52. }
  53. }
  54. // Encrypt length as AES ECB.
  55. iv1 := []byte{'\x01'}
  56. iv1 = append(iv1, iv...)
  57. iv1 = append(iv1, u64tob(uint64(plaintextN))...)
  58. W1 := make([]byte, len(iv1))
  59. enc.blockMode.CryptBlocks(W1, iv1)
  60. // Encrypt plaintext with AES CTR.
  61. iv2 := []byte("\x00\x00\x00\x00\x00\x00\x00\x00\x02")
  62. iv2 = append(iv2, iv...)
  63. stream := cipher.NewCTR(enc.block, iv2)
  64. padN := aes.BlockSize - (plaintextN % aes.BlockSize)
  65. plaintext = append(plaintext, make([]byte, padN)...)
  66. W2 := make([]byte, len(plaintext))
  67. stream.XORKeyStream(W2, plaintext)
  68. W2, plaintext = W2[:plaintextN], plaintext[:plaintextN]
  69. // Concatenate both sections.
  70. ciphertext := append(W1[:len(W1):len(W1)], W2...)
  71. // Sign the message & limit size to AES block size.
  72. mac := hmac.New(sha512.New, K2)
  73. mac.Write(ciphertext)
  74. T := mac.Sum(nil)
  75. T = T[:aes.BlockSize]
  76. return append(ciphertext, T...), nil
  77. }
  78. type Decrypter struct {
  79. block cipher.Block
  80. blockMode cipher.BlockMode
  81. }
  82. func NewDecrypter() (*Decrypter, error) {
  83. blk, err := aes.NewCipher(K1)
  84. if err != nil {
  85. return nil, err
  86. }
  87. return &Decrypter{
  88. block: blk,
  89. blockMode: ecb.NewDecrypter(blk),
  90. }, nil
  91. }
  92. func (dec *Decrypter) Decrypt(ciphertext []byte) ([]byte, error) {
  93. if len(ciphertext) < 16 {
  94. return nil, ErrShortCiphertext
  95. }
  96. // Decrypt header.
  97. L := make([]byte, 16)
  98. dec.block.Decrypt(L, ciphertext[:16])
  99. plaintext_length := binary.BigEndian.Uint64(L[8:16])
  100. if plaintext_length > math.MaxUint32 {
  101. return nil, ErrInvalidMessageLength
  102. }
  103. ciphertext_length := plaintext_length + CTXT_EXPANSION
  104. if len(ciphertext) < int(ciphertext_length) {
  105. return nil, ErrShortCiphertext
  106. }
  107. ciphertext = ciphertext[:ciphertext_length:ciphertext_length]
  108. W1 := ciphertext[0:aes.BlockSize:aes.BlockSize]
  109. W2 := ciphertext[aes.BlockSize : aes.BlockSize+plaintext_length : aes.BlockSize+plaintext_length]
  110. T_start := aes.BlockSize + plaintext_length
  111. T_end := aes.BlockSize + plaintext_length + aes.BlockSize
  112. T_expected := ciphertext[T_start:T_end:T_end]
  113. // Sign the message & limit size to AES block size.
  114. mac := hmac.New(sha512.New, K2)
  115. mac.Write(append(W1, W2...))
  116. if !hmac.Equal(mac.Sum(nil)[:aes.BlockSize], T_expected) {
  117. return nil, ErrHMACVerificationFailed
  118. }
  119. // Decrypt ciphertext with AES CTR.
  120. iv := make([]byte, aes.BlockSize)
  121. dec.block.Decrypt(iv, W1)
  122. iv2 := make([]byte, aes.BlockSize)
  123. iv2[8] = '\x02'
  124. copy(iv2[9:], iv[1:8])
  125. stream := cipher.NewCTR(dec.block, iv2)
  126. plaintext := make([]byte, plaintext_length)
  127. stream.XORKeyStream(plaintext, W2)
  128. return plaintext, nil
  129. }
  130. func (dec *Decrypter) CiphertextLen(ciphertext []byte) int {
  131. L := make([]byte, 16)
  132. dec.block.Decrypt(L, ciphertext[:16])
  133. return int(binary.BigEndian.Uint32(L[12:16])) + CTXT_EXPANSION
  134. }
  135. // u64tob returns the big endian representation of a uint64 value.
  136. func u64tob(i uint64) []byte {
  137. b := make([]byte, 8)
  138. binary.BigEndian.PutUint64(b, i)
  139. return b
  140. }