github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/storage/encryption/encryption.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 // 10 // 11 // 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 25 package encryption 26 27 import ( 28 "crypto/rand" 29 "encoding/binary" 30 "fmt" 31 "hash" 32 ) 33 34 const KeyLength = 32 35 36 type Key []byte 37 38 type Encryption interface { 39 Encrypt(data []byte, key Key) ([]byte, error) 40 Decrypt(data []byte, key Key) ([]byte, error) 41 } 42 43 type encryption struct { 44 padding int 45 initCtr uint32 46 hashFunc func() hash.Hash 47 } 48 49 func New(padding int, initCtr uint32, hashFunc func() hash.Hash) *encryption { 50 return &encryption{ 51 padding: padding, 52 initCtr: initCtr, 53 hashFunc: hashFunc, 54 } 55 } 56 57 func (e *encryption) Encrypt(data []byte, key Key) ([]byte, error) { 58 length := len(data) 59 isFixedPadding := e.padding > 0 60 if isFixedPadding && length > e.padding { 61 return nil, fmt.Errorf("Data length longer than padding, data length %v padding %v", length, e.padding) 62 } 63 64 paddedData := data 65 if isFixedPadding && length < e.padding { 66 paddedData = make([]byte, e.padding) 67 copy(paddedData[:length], data) 68 rand.Read(paddedData[length:]) 69 } 70 return e.transform(paddedData, key), nil 71 } 72 73 func (e *encryption) Decrypt(data []byte, key Key) ([]byte, error) { 74 length := len(data) 75 if e.padding > 0 && length != e.padding { 76 return nil, fmt.Errorf("Data length different than padding, data length %v padding %v", length, e.padding) 77 } 78 79 return e.transform(data, key), nil 80 } 81 82 func (e *encryption) transform(data []byte, key Key) []byte { 83 dataLength := len(data) 84 transformedData := make([]byte, dataLength) 85 hasher := e.hashFunc() 86 ctr := e.initCtr 87 hashSize := hasher.Size() 88 for i := 0; i < dataLength; i += hashSize { 89 hasher.Write(key) 90 91 ctrBytes := make([]byte, 4) 92 binary.LittleEndian.PutUint32(ctrBytes, ctr) 93 94 hasher.Write(ctrBytes) 95 96 ctrHash := hasher.Sum(nil) 97 hasher.Reset() 98 hasher.Write(ctrHash) 99 100 segmentKey := hasher.Sum(nil) 101 102 hasher.Reset() 103 104 segmentSize := min(hashSize, dataLength-i) 105 for j := 0; j < segmentSize; j++ { 106 transformedData[i+j] = data[i+j] ^ segmentKey[j] 107 } 108 ctr++ 109 } 110 return transformedData 111 } 112 113 func GenerateRandomKey() (Key, error) { 114 key := make([]byte, KeyLength) 115 _, err := rand.Read(key) 116 return key, err 117 } 118 119 func min(x, y int) int { 120 if x < y { 121 return x 122 } 123 return y 124 }