github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/signer/storage/aes_gcm_storage.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 //版权所有2018 Go Ethereum作者 10 //此文件是Go以太坊的一部分。 11 // 12 //Go以太坊是免费软件:您可以重新发布和/或修改它 13 //根据GNU通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊的分布希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU通用公共许可证了解更多详细信息。 21 // 22 //你应该已经收到一份GNU通用公共许可证的副本 23 //一起去以太坊吧。如果没有,请参见<http://www.gnu.org/licenses/>。 24 // 25 26 package storage 27 28 import ( 29 "crypto/aes" 30 "crypto/cipher" 31 "crypto/rand" 32 "encoding/json" 33 "io" 34 "io/ioutil" 35 "os" 36 37 "github.com/ethereum/go-ethereum/log" 38 ) 39 40 type storedCredential struct { 41 //四维 42 Iv []byte `json:"iv"` 43 //密文 44 CipherText []byte `json:"c"` 45 } 46 47 //AESEncryptedStorage是一种由JSON故障支持的存储类型。json文件包含 48 //密钥值映射,其中密钥没有加密,只有值是加密的。 49 type AESEncryptedStorage struct { 50 //要读取/写入凭据的文件 51 filename string 52 //密钥存储在base64中 53 key []byte 54 } 55 56 //newaesEncryptedStorage创建由给定文件/密钥支持的新加密存储 57 func NewAESEncryptedStorage(filename string, key []byte) *AESEncryptedStorage { 58 return &AESEncryptedStorage{ 59 filename: filename, 60 key: key, 61 } 62 } 63 64 //按键存储值。0长度键导致无操作 65 func (s *AESEncryptedStorage) Put(key, value string) { 66 if len(key) == 0 { 67 return 68 } 69 data, err := s.readEncryptedStorage() 70 if err != nil { 71 log.Warn("Failed to read encrypted storage", "err", err, "file", s.filename) 72 return 73 } 74 ciphertext, iv, err := encrypt(s.key, []byte(value)) 75 if err != nil { 76 log.Warn("Failed to encrypt entry", "err", err) 77 return 78 } 79 encrypted := storedCredential{Iv: iv, CipherText: ciphertext} 80 data[key] = encrypted 81 if err = s.writeEncryptedStorage(data); err != nil { 82 log.Warn("Failed to write entry", "err", err) 83 } 84 } 85 86 //get返回以前存储的值,如果该值不存在或键的长度为0,则返回空字符串 87 func (s *AESEncryptedStorage) Get(key string) string { 88 if len(key) == 0 { 89 return "" 90 } 91 data, err := s.readEncryptedStorage() 92 if err != nil { 93 log.Warn("Failed to read encrypted storage", "err", err, "file", s.filename) 94 return "" 95 } 96 encrypted, exist := data[key] 97 if !exist { 98 log.Warn("Key does not exist", "key", key) 99 return "" 100 } 101 entry, err := decrypt(s.key, encrypted.Iv, encrypted.CipherText) 102 if err != nil { 103 log.Warn("Failed to decrypt key", "key", key) 104 return "" 105 } 106 return string(entry) 107 } 108 109 //ReadEncryptedStorage使用加密的凭据读取文件 110 func (s *AESEncryptedStorage) readEncryptedStorage() (map[string]storedCredential, error) { 111 creds := make(map[string]storedCredential) 112 raw, err := ioutil.ReadFile(s.filename) 113 114 if err != nil { 115 if os.IsNotExist(err) { 116 //还不存在 117 return creds, nil 118 } 119 log.Warn("Failed to read encrypted storage", "err", err, "file", s.filename) 120 } 121 if err = json.Unmarshal(raw, &creds); err != nil { 122 log.Warn("Failed to unmarshal encrypted storage", "err", err, "file", s.filename) 123 return nil, err 124 } 125 return creds, nil 126 } 127 128 //WriteEncryptedStorage使用加密的凭据写入文件 129 func (s *AESEncryptedStorage) writeEncryptedStorage(creds map[string]storedCredential) error { 130 raw, err := json.Marshal(creds) 131 if err != nil { 132 return err 133 } 134 if err = ioutil.WriteFile(s.filename, raw, 0600); err != nil { 135 return err 136 } 137 return nil 138 } 139 140 func encrypt(key []byte, plaintext []byte) ([]byte, []byte, error) { 141 block, err := aes.NewCipher(key) 142 if err != nil { 143 return nil, nil, err 144 } 145 aesgcm, err := cipher.NewGCM(block) 146 nonce := make([]byte, aesgcm.NonceSize()) 147 if _, err := io.ReadFull(rand.Reader, nonce); err != nil { 148 return nil, nil, err 149 } 150 if err != nil { 151 return nil, nil, err 152 } 153 ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil) 154 return ciphertext, nonce, nil 155 } 156 157 func decrypt(key []byte, nonce []byte, ciphertext []byte) ([]byte, error) { 158 block, err := aes.NewCipher(key) 159 if err != nil { 160 return nil, err 161 } 162 aesgcm, err := cipher.NewGCM(block) 163 if err != nil { 164 return nil, err 165 } 166 plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil) 167 if err != nil { 168 return nil, err 169 } 170 return plaintext, nil 171 }