encryption.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Copyright 2018 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package encryption
  17. import (
  18. "crypto/rand"
  19. "encoding/binary"
  20. "fmt"
  21. "hash"
  22. "sync"
  23. )
  24. const KeyLength = 32
  25. type Key []byte
  26. type Encryption interface {
  27. Encrypt(data []byte) ([]byte, error)
  28. Decrypt(data []byte) ([]byte, error)
  29. }
  30. type encryption struct {
  31. key Key // the encryption key (hashSize bytes long)
  32. keyLen int // length of the key = length of blockcipher block
  33. padding int // encryption will pad the data upto this if > 0
  34. initCtr uint32 // initial counter used for counter mode blockcipher
  35. hashFunc func() hash.Hash // hasher constructor function
  36. }
  37. // New constructs a new encryptor/decryptor
  38. func New(key Key, padding int, initCtr uint32, hashFunc func() hash.Hash) *encryption {
  39. return &encryption{
  40. key: key,
  41. keyLen: len(key),
  42. padding: padding,
  43. initCtr: initCtr,
  44. hashFunc: hashFunc,
  45. }
  46. }
  47. // Encrypt encrypts the data and does padding if specified
  48. func (e *encryption) Encrypt(data []byte) ([]byte, error) {
  49. length := len(data)
  50. outLength := length
  51. isFixedPadding := e.padding > 0
  52. if isFixedPadding {
  53. if length > e.padding {
  54. return nil, fmt.Errorf("Data length longer than padding, data length %v padding %v", length, e.padding)
  55. }
  56. outLength = e.padding
  57. }
  58. out := make([]byte, outLength)
  59. e.transform(data, out)
  60. return out, nil
  61. }
  62. // Decrypt decrypts the data, if padding was used caller must know original length and truncate
  63. func (e *encryption) Decrypt(data []byte) ([]byte, error) {
  64. length := len(data)
  65. if e.padding > 0 && length != e.padding {
  66. return nil, fmt.Errorf("Data length different than padding, data length %v padding %v", length, e.padding)
  67. }
  68. out := make([]byte, length)
  69. e.transform(data, out)
  70. return out, nil
  71. }
  72. //
  73. func (e *encryption) transform(in, out []byte) {
  74. inLength := len(in)
  75. wg := sync.WaitGroup{}
  76. wg.Add((inLength-1)/e.keyLen + 1)
  77. for i := 0; i < inLength; i += e.keyLen {
  78. l := min(e.keyLen, inLength-i)
  79. // call transformations per segment (asyncronously)
  80. go func(i int, x, y []byte) {
  81. defer wg.Done()
  82. e.Transcrypt(i, x, y)
  83. }(i/e.keyLen, in[i:i+l], out[i:i+l])
  84. }
  85. // pad the rest if out is longer
  86. pad(out[inLength:])
  87. wg.Wait()
  88. }
  89. // used for segmentwise transformation
  90. // if in is shorter than out, padding is used
  91. func (e *encryption) Transcrypt(i int, in []byte, out []byte) {
  92. // first hash key with counter (initial counter + i)
  93. hasher := e.hashFunc()
  94. hasher.Write(e.key)
  95. ctrBytes := make([]byte, 4)
  96. binary.LittleEndian.PutUint32(ctrBytes, uint32(i)+e.initCtr)
  97. hasher.Write(ctrBytes)
  98. ctrHash := hasher.Sum(nil)
  99. hasher.Reset()
  100. // second round of hashing for selective disclosure
  101. hasher.Write(ctrHash)
  102. segmentKey := hasher.Sum(nil)
  103. hasher.Reset()
  104. // XOR bytes uptil length of in (out must be at least as long)
  105. inLength := len(in)
  106. for j := 0; j < inLength; j++ {
  107. out[j] = in[j] ^ segmentKey[j]
  108. }
  109. // insert padding if out is longer
  110. pad(out[inLength:])
  111. }
  112. func pad(b []byte) {
  113. l := len(b)
  114. for total := 0; total < l; {
  115. read, _ := rand.Read(b[total:])
  116. total += read
  117. }
  118. }
  119. // GenerateRandomKey generates a random key of length l
  120. func GenerateRandomKey(l int) Key {
  121. key := make([]byte, l)
  122. var total int
  123. for total < l {
  124. read, _ := rand.Read(key[total:])
  125. total += read
  126. }
  127. return key
  128. }
  129. func min(x, y int) int {
  130. if x < y {
  131. return x
  132. }
  133. return y
  134. }