github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/whisper/whisperv6/message.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 12:09:51</date> 10 //</624342690795884544> 11 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 // 25 // 26 // 27 28 // 29 30 package whisperv6 31 32 import ( 33 "crypto/aes" 34 "crypto/cipher" 35 "crypto/ecdsa" 36 crand "crypto/rand" 37 "encoding/binary" 38 "errors" 39 mrand "math/rand" 40 "strconv" 41 42 "github.com/ethereum/go-ethereum/common" 43 "github.com/ethereum/go-ethereum/crypto" 44 "github.com/ethereum/go-ethereum/crypto/ecies" 45 "github.com/ethereum/go-ethereum/log" 46 ) 47 48 // 49 // 50 type MessageParams struct { 51 TTL uint32 52 Src *ecdsa.PrivateKey 53 Dst *ecdsa.PublicKey 54 KeySym []byte 55 Topic TopicType 56 WorkTime uint32 57 PoW float64 58 Payload []byte 59 Padding []byte 60 } 61 62 // 63 // 64 // 65 type sentMessage struct { 66 Raw []byte 67 } 68 69 // 70 // 71 type ReceivedMessage struct { 72 Raw []byte 73 74 Payload []byte 75 Padding []byte 76 Signature []byte 77 Salt []byte 78 79 PoW float64 // 80 Sent uint32 // 81 TTL uint32 // 82 Src *ecdsa.PublicKey // 83 Dst *ecdsa.PublicKey // 84 Topic TopicType 85 86 SymKeyHash common.Hash // 87 EnvelopeHash common.Hash // 88 } 89 90 func isMessageSigned(flags byte) bool { 91 return (flags & signatureFlag) != 0 92 } 93 94 func (msg *ReceivedMessage) isSymmetricEncryption() bool { 95 return msg.SymKeyHash != common.Hash{} 96 } 97 98 func (msg *ReceivedMessage) isAsymmetricEncryption() bool { 99 return msg.Dst != nil 100 } 101 102 // 103 func NewSentMessage(params *MessageParams) (*sentMessage, error) { 104 const payloadSizeFieldMaxSize = 4 105 msg := sentMessage{} 106 msg.Raw = make([]byte, 1, 107 flagsLength+payloadSizeFieldMaxSize+len(params.Payload)+len(params.Padding)+signatureLength+padSizeLimit) 108 msg.Raw[0] = 0 // 109 msg.addPayloadSizeField(params.Payload) 110 msg.Raw = append(msg.Raw, params.Payload...) 111 err := msg.appendPadding(params) 112 return &msg, err 113 } 114 115 // 116 func (msg *sentMessage) addPayloadSizeField(payload []byte) { 117 fieldSize := getSizeOfPayloadSizeField(payload) 118 field := make([]byte, 4) 119 binary.LittleEndian.PutUint32(field, uint32(len(payload))) 120 field = field[:fieldSize] 121 msg.Raw = append(msg.Raw, field...) 122 msg.Raw[0] |= byte(fieldSize) 123 } 124 125 // 126 func getSizeOfPayloadSizeField(payload []byte) int { 127 s := 1 128 for i := len(payload); i >= 256; i /= 256 { 129 s++ 130 } 131 return s 132 } 133 134 // 135 // 136 func (msg *sentMessage) appendPadding(params *MessageParams) error { 137 if len(params.Padding) != 0 { 138 // 139 msg.Raw = append(msg.Raw, params.Padding...) 140 return nil 141 } 142 143 rawSize := flagsLength + getSizeOfPayloadSizeField(params.Payload) + len(params.Payload) 144 if params.Src != nil { 145 rawSize += signatureLength 146 } 147 odd := rawSize % padSizeLimit 148 paddingSize := padSizeLimit - odd 149 pad := make([]byte, paddingSize) 150 _, err := crand.Read(pad) 151 if err != nil { 152 return err 153 } 154 if !validateDataIntegrity(pad, paddingSize) { 155 return errors.New("failed to generate random padding of size " + strconv.Itoa(paddingSize)) 156 } 157 msg.Raw = append(msg.Raw, pad...) 158 return nil 159 } 160 161 // 162 // 163 func (msg *sentMessage) sign(key *ecdsa.PrivateKey) error { 164 if isMessageSigned(msg.Raw[0]) { 165 // 166 log.Error("failed to sign the message: already signed") 167 return nil 168 } 169 170 msg.Raw[0] |= signatureFlag // 171 hash := crypto.Keccak256(msg.Raw) 172 signature, err := crypto.Sign(hash, key) 173 if err != nil { 174 msg.Raw[0] &= (0xFF ^ signatureFlag) // 175 return err 176 } 177 msg.Raw = append(msg.Raw, signature...) 178 return nil 179 } 180 181 // 182 func (msg *sentMessage) encryptAsymmetric(key *ecdsa.PublicKey) error { 183 if !ValidatePublicKey(key) { 184 return errors.New("invalid public key provided for asymmetric encryption") 185 } 186 encrypted, err := ecies.Encrypt(crand.Reader, ecies.ImportECDSAPublic(key), msg.Raw, nil, nil) 187 if err == nil { 188 msg.Raw = encrypted 189 } 190 return err 191 } 192 193 // 194 // 195 func (msg *sentMessage) encryptSymmetric(key []byte) (err error) { 196 if !validateDataIntegrity(key, aesKeyLength) { 197 return errors.New("invalid key provided for symmetric encryption, size: " + strconv.Itoa(len(key))) 198 } 199 block, err := aes.NewCipher(key) 200 if err != nil { 201 return err 202 } 203 aesgcm, err := cipher.NewGCM(block) 204 if err != nil { 205 return err 206 } 207 salt, err := generateSecureRandomData(aesNonceLength) // 208 if err != nil { 209 return err 210 } 211 encrypted := aesgcm.Seal(nil, salt, msg.Raw, nil) 212 msg.Raw = append(encrypted, salt...) 213 return nil 214 } 215 216 // 217 // 218 // 219 // 220 // 221 func generateSecureRandomData(length int) ([]byte, error) { 222 x := make([]byte, length) 223 y := make([]byte, length) 224 res := make([]byte, length) 225 226 _, err := crand.Read(x) 227 if err != nil { 228 return nil, err 229 } else if !validateDataIntegrity(x, length) { 230 return nil, errors.New("crypto/rand failed to generate secure random data") 231 } 232 _, err = mrand.Read(y) 233 if err != nil { 234 return nil, err 235 } else if !validateDataIntegrity(y, length) { 236 return nil, errors.New("math/rand failed to generate secure random data") 237 } 238 for i := 0; i < length; i++ { 239 res[i] = x[i] ^ y[i] 240 } 241 if !validateDataIntegrity(res, length) { 242 return nil, errors.New("failed to generate secure random data") 243 } 244 return res, nil 245 } 246 247 // 248 func (msg *sentMessage) Wrap(options *MessageParams) (envelope *Envelope, err error) { 249 if options.TTL == 0 { 250 options.TTL = DefaultTTL 251 } 252 if options.Src != nil { 253 if err = msg.sign(options.Src); err != nil { 254 return nil, err 255 } 256 } 257 if options.Dst != nil { 258 err = msg.encryptAsymmetric(options.Dst) 259 } else if options.KeySym != nil { 260 err = msg.encryptSymmetric(options.KeySym) 261 } else { 262 err = errors.New("unable to encrypt the message: neither symmetric nor assymmetric key provided") 263 } 264 if err != nil { 265 return nil, err 266 } 267 268 envelope = NewEnvelope(options.TTL, options.Topic, msg) 269 if err = envelope.Seal(options); err != nil { 270 return nil, err 271 } 272 return envelope, nil 273 } 274 275 // 276 // 277 func (msg *ReceivedMessage) decryptSymmetric(key []byte) error { 278 // 279 if len(msg.Raw) < aesNonceLength { 280 return errors.New("missing salt or invalid payload in symmetric message") 281 } 282 salt := msg.Raw[len(msg.Raw)-aesNonceLength:] 283 284 block, err := aes.NewCipher(key) 285 if err != nil { 286 return err 287 } 288 aesgcm, err := cipher.NewGCM(block) 289 if err != nil { 290 return err 291 } 292 decrypted, err := aesgcm.Open(nil, salt, msg.Raw[:len(msg.Raw)-aesNonceLength], nil) 293 if err != nil { 294 return err 295 } 296 msg.Raw = decrypted 297 msg.Salt = salt 298 return nil 299 } 300 301 // 302 func (msg *ReceivedMessage) decryptAsymmetric(key *ecdsa.PrivateKey) error { 303 decrypted, err := ecies.ImportECDSA(key).Decrypt(msg.Raw, nil, nil) 304 if err == nil { 305 msg.Raw = decrypted 306 } 307 return err 308 } 309 310 // 311 func (msg *ReceivedMessage) ValidateAndParse() bool { 312 end := len(msg.Raw) 313 if end < 1 { 314 return false 315 } 316 317 if isMessageSigned(msg.Raw[0]) { 318 end -= signatureLength 319 if end <= 1 { 320 return false 321 } 322 msg.Signature = msg.Raw[end : end+signatureLength] 323 msg.Src = msg.SigToPubKey() 324 if msg.Src == nil { 325 return false 326 } 327 } 328 329 beg := 1 330 payloadSize := 0 331 sizeOfPayloadSizeField := int(msg.Raw[0] & SizeMask) // 332 if sizeOfPayloadSizeField != 0 { 333 payloadSize = int(bytesToUintLittleEndian(msg.Raw[beg : beg+sizeOfPayloadSizeField])) 334 if payloadSize+1 > end { 335 return false 336 } 337 beg += sizeOfPayloadSizeField 338 msg.Payload = msg.Raw[beg : beg+payloadSize] 339 } 340 341 beg += payloadSize 342 msg.Padding = msg.Raw[beg:end] 343 return true 344 } 345 346 // 347 // 348 func (msg *ReceivedMessage) SigToPubKey() *ecdsa.PublicKey { 349 defer func() { recover() }() // 350 351 pub, err := crypto.SigToPub(msg.hash(), msg.Signature) 352 if err != nil { 353 log.Error("failed to recover public key from signature", "err", err) 354 return nil 355 } 356 return pub 357 } 358 359 // 360 func (msg *ReceivedMessage) hash() []byte { 361 if isMessageSigned(msg.Raw[0]) { 362 sz := len(msg.Raw) - signatureLength 363 return crypto.Keccak256(msg.Raw[:sz]) 364 } 365 return crypto.Keccak256(msg.Raw) 366 } 367