github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/storage/encryption/encryption.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:44</date> 10 //</624450118485020672> 11 12 13 package encryption 14 15 import ( 16 "crypto/rand" 17 "encoding/binary" 18 "fmt" 19 "hash" 20 "sync" 21 ) 22 23 const KeyLength = 32 24 25 type Key []byte 26 27 type Encryption interface { 28 Encrypt(data []byte) ([]byte, error) 29 Decrypt(data []byte) ([]byte, error) 30 } 31 32 type encryption struct { 33 key Key //加密密钥(hashsize bytes long) 34 keyLen int //密钥长度=分组密码块的长度 35 padding int //如果大于0,加密会将数据填充到此 36 initCtr uint32 //用于计数器模式块密码的初始计数器 37 hashFunc func() hash.Hash //哈希构造函数函数 38 } 39 40 //new构造新的加密/解密程序 41 func New(key Key, padding int, initCtr uint32, hashFunc func() hash.Hash) *encryption { 42 return &encryption{ 43 key: key, 44 keyLen: len(key), 45 padding: padding, 46 initCtr: initCtr, 47 hashFunc: hashFunc, 48 } 49 } 50 51 //Encrypt加密数据并在指定时进行填充 52 func (e *encryption) Encrypt(data []byte) ([]byte, error) { 53 length := len(data) 54 outLength := length 55 isFixedPadding := e.padding > 0 56 if isFixedPadding { 57 if length > e.padding { 58 return nil, fmt.Errorf("Data length longer than padding, data length %v padding %v", length, e.padding) 59 } 60 outLength = e.padding 61 } 62 out := make([]byte, outLength) 63 e.transform(data, out) 64 return out, nil 65 } 66 67 //decrypt解密数据,如果使用填充,调用方必须知道原始长度并截断 68 func (e *encryption) Decrypt(data []byte) ([]byte, error) { 69 length := len(data) 70 if e.padding > 0 && length != e.padding { 71 return nil, fmt.Errorf("Data length different than padding, data length %v padding %v", length, e.padding) 72 } 73 out := make([]byte, length) 74 e.transform(data, out) 75 return out, nil 76 } 77 78 // 79 func (e *encryption) transform(in, out []byte) { 80 inLength := len(in) 81 wg := sync.WaitGroup{} 82 wg.Add((inLength-1)/e.keyLen + 1) 83 for i := 0; i < inLength; i += e.keyLen { 84 l := min(e.keyLen, inLength-i) 85 //每段调用转换(异步) 86 go func(i int, x, y []byte) { 87 defer wg.Done() 88 e.Transcrypt(i, x, y) 89 }(i/e.keyLen, in[i:i+l], out[i:i+l]) 90 } 91 //如果出局时间较长,则补上其余部分。 92 pad(out[inLength:]) 93 wg.Wait() 94 } 95 96 //用于分段转换 97 //如果输入短于输出,则使用填充 98 func (e *encryption) Transcrypt(i int, in []byte, out []byte) { 99 //带计数器的第一个哈希键(初始计数器+I) 100 hasher := e.hashFunc() 101 hasher.Write(e.key) 102 103 ctrBytes := make([]byte, 4) 104 binary.LittleEndian.PutUint32(ctrBytes, uint32(i)+e.initCtr) 105 hasher.Write(ctrBytes) 106 107 ctrHash := hasher.Sum(nil) 108 hasher.Reset() 109 110 //第二轮哈希选择披露 111 hasher.Write(ctrHash) 112 segmentKey := hasher.Sum(nil) 113 hasher.Reset() 114 115 //输入的XOR字节正常运行时间长度(输出必须至少与之相同) 116 inLength := len(in) 117 for j := 0; j < inLength; j++ { 118 out[j] = in[j] ^ segmentKey[j] 119 } 120 //如果超出长度,则插入填充 121 pad(out[inLength:]) 122 } 123 124 func pad(b []byte) { 125 l := len(b) 126 for total := 0; total < l; { 127 read, _ := rand.Read(b[total:]) 128 total += read 129 } 130 } 131 132 //GenerateRandomKey生成长度为l的随机键 133 func GenerateRandomKey(l int) Key { 134 key := make([]byte, l) 135 var total int 136 for total < l { 137 read, _ := rand.Read(key[total:]) 138 total += read 139 } 140 return key 141 } 142 143 func min(x, y int) int { 144 if x < y { 145 return x 146 } 147 return y 148 } 149