github.com/phillinzzz/newBsc@v1.1.6/p2p/discover/v5wire/encoding.go (about) 1 // Copyright 2019 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 17 package v5wire 18 19 import ( 20 "bytes" 21 "crypto/aes" 22 "crypto/cipher" 23 "crypto/ecdsa" 24 crand "crypto/rand" 25 "crypto/sha256" 26 "encoding/binary" 27 "errors" 28 "fmt" 29 "hash" 30 31 "github.com/phillinzzz/newBsc/common/mclock" 32 "github.com/phillinzzz/newBsc/p2p/enode" 33 "github.com/phillinzzz/newBsc/p2p/enr" 34 "github.com/phillinzzz/newBsc/rlp" 35 ) 36 37 // TODO concurrent WHOAREYOU tie-breaker 38 // TODO rehandshake after X packets 39 40 // Header represents a packet header. 41 type Header struct { 42 IV [sizeofMaskingIV]byte 43 StaticHeader 44 AuthData []byte 45 46 src enode.ID // used by decoder 47 } 48 49 // StaticHeader contains the static fields of a packet header. 50 type StaticHeader struct { 51 ProtocolID [6]byte 52 Version uint16 53 Flag byte 54 Nonce Nonce 55 AuthSize uint16 56 } 57 58 // Authdata layouts. 59 type ( 60 whoareyouAuthData struct { 61 IDNonce [16]byte // ID proof data 62 RecordSeq uint64 // highest known ENR sequence of requester 63 } 64 65 handshakeAuthData struct { 66 h struct { 67 SrcID enode.ID 68 SigSize byte // ignature data 69 PubkeySize byte // offset of 70 } 71 // Trailing variable-size data. 72 signature, pubkey, record []byte 73 } 74 75 messageAuthData struct { 76 SrcID enode.ID 77 } 78 ) 79 80 // Packet header flag values. 81 const ( 82 flagMessage = iota 83 flagWhoareyou 84 flagHandshake 85 ) 86 87 // Protocol constants. 88 const ( 89 version = 1 90 minVersion = 1 91 sizeofMaskingIV = 16 92 93 minMessageSize = 48 // this refers to data after static headers 94 randomPacketMsgSize = 20 95 ) 96 97 var protocolID = [6]byte{'d', 'i', 's', 'c', 'v', '5'} 98 99 // Errors. 100 var ( 101 errTooShort = errors.New("packet too short") 102 errInvalidHeader = errors.New("invalid packet header") 103 errInvalidFlag = errors.New("invalid flag value in header") 104 errMinVersion = errors.New("version of packet header below minimum") 105 errMsgTooShort = errors.New("message/handshake packet below minimum size") 106 errAuthSize = errors.New("declared auth size is beyond packet length") 107 errUnexpectedHandshake = errors.New("unexpected auth response, not in handshake") 108 errInvalidAuthKey = errors.New("invalid ephemeral pubkey") 109 errNoRecord = errors.New("expected ENR in handshake but none sent") 110 errInvalidNonceSig = errors.New("invalid ID nonce signature") 111 errMessageTooShort = errors.New("message contains no data") 112 errMessageDecrypt = errors.New("cannot decrypt message") 113 ) 114 115 // Public errors. 116 var ( 117 ErrInvalidReqID = errors.New("request ID larger than 8 bytes") 118 ) 119 120 // Packet sizes. 121 var ( 122 sizeofStaticHeader = binary.Size(StaticHeader{}) 123 sizeofWhoareyouAuthData = binary.Size(whoareyouAuthData{}) 124 sizeofHandshakeAuthData = binary.Size(handshakeAuthData{}.h) 125 sizeofMessageAuthData = binary.Size(messageAuthData{}) 126 sizeofStaticPacketData = sizeofMaskingIV + sizeofStaticHeader 127 ) 128 129 // Codec encodes and decodes Discovery v5 packets. 130 // This type is not safe for concurrent use. 131 type Codec struct { 132 sha256 hash.Hash 133 localnode *enode.LocalNode 134 privkey *ecdsa.PrivateKey 135 sc *SessionCache 136 137 // encoder buffers 138 buf bytes.Buffer // whole packet 139 headbuf bytes.Buffer // packet header 140 msgbuf bytes.Buffer // message RLP plaintext 141 msgctbuf []byte // message data ciphertext 142 143 // decoder buffer 144 reader bytes.Reader 145 } 146 147 // NewCodec creates a wire codec. 148 func NewCodec(ln *enode.LocalNode, key *ecdsa.PrivateKey, clock mclock.Clock) *Codec { 149 c := &Codec{ 150 sha256: sha256.New(), 151 localnode: ln, 152 privkey: key, 153 sc: NewSessionCache(1024, clock), 154 } 155 return c 156 } 157 158 // Encode encodes a packet to a node. 'id' and 'addr' specify the destination node. The 159 // 'challenge' parameter should be the most recently received WHOAREYOU packet from that 160 // node. 161 func (c *Codec) Encode(id enode.ID, addr string, packet Packet, challenge *Whoareyou) ([]byte, Nonce, error) { 162 // Create the packet header. 163 var ( 164 head Header 165 session *session 166 msgData []byte 167 err error 168 ) 169 switch { 170 case packet.Kind() == WhoareyouPacket: 171 head, err = c.encodeWhoareyou(id, packet.(*Whoareyou)) 172 case challenge != nil: 173 // We have an unanswered challenge, send handshake. 174 head, session, err = c.encodeHandshakeHeader(id, addr, challenge) 175 default: 176 session = c.sc.session(id, addr) 177 if session != nil { 178 // There is a session, use it. 179 head, err = c.encodeMessageHeader(id, session) 180 } else { 181 // No keys, send random data to kick off the handshake. 182 head, msgData, err = c.encodeRandom(id) 183 } 184 } 185 if err != nil { 186 return nil, Nonce{}, err 187 } 188 189 // Generate masking IV. 190 if err := c.sc.maskingIVGen(head.IV[:]); err != nil { 191 return nil, Nonce{}, fmt.Errorf("can't generate masking IV: %v", err) 192 } 193 194 // Encode header data. 195 c.writeHeaders(&head) 196 197 // Store sent WHOAREYOU challenges. 198 if challenge, ok := packet.(*Whoareyou); ok { 199 challenge.ChallengeData = bytesCopy(&c.buf) 200 c.sc.storeSentHandshake(id, addr, challenge) 201 } else if msgData == nil { 202 headerData := c.buf.Bytes() 203 msgData, err = c.encryptMessage(session, packet, &head, headerData) 204 if err != nil { 205 return nil, Nonce{}, err 206 } 207 } 208 209 enc, err := c.EncodeRaw(id, head, msgData) 210 return enc, head.Nonce, err 211 } 212 213 // EncodeRaw encodes a packet with the given header. 214 func (c *Codec) EncodeRaw(id enode.ID, head Header, msgdata []byte) ([]byte, error) { 215 c.writeHeaders(&head) 216 217 // Apply masking. 218 masked := c.buf.Bytes()[sizeofMaskingIV:] 219 mask := head.mask(id) 220 mask.XORKeyStream(masked[:], masked[:]) 221 222 // Write message data. 223 c.buf.Write(msgdata) 224 return c.buf.Bytes(), nil 225 } 226 227 func (c *Codec) writeHeaders(head *Header) { 228 c.buf.Reset() 229 c.buf.Write(head.IV[:]) 230 binary.Write(&c.buf, binary.BigEndian, &head.StaticHeader) 231 c.buf.Write(head.AuthData) 232 } 233 234 // makeHeader creates a packet header. 235 func (c *Codec) makeHeader(toID enode.ID, flag byte, authsizeExtra int) Header { 236 var authsize int 237 switch flag { 238 case flagMessage: 239 authsize = sizeofMessageAuthData 240 case flagWhoareyou: 241 authsize = sizeofWhoareyouAuthData 242 case flagHandshake: 243 authsize = sizeofHandshakeAuthData 244 default: 245 panic(fmt.Errorf("BUG: invalid packet header flag %x", flag)) 246 } 247 authsize += authsizeExtra 248 if authsize > int(^uint16(0)) { 249 panic(fmt.Errorf("BUG: auth size %d overflows uint16", authsize)) 250 } 251 return Header{ 252 StaticHeader: StaticHeader{ 253 ProtocolID: protocolID, 254 Version: version, 255 Flag: flag, 256 AuthSize: uint16(authsize), 257 }, 258 } 259 } 260 261 // encodeRandom encodes a packet with random content. 262 func (c *Codec) encodeRandom(toID enode.ID) (Header, []byte, error) { 263 head := c.makeHeader(toID, flagMessage, 0) 264 265 // Encode auth data. 266 auth := messageAuthData{SrcID: c.localnode.ID()} 267 if _, err := crand.Read(head.Nonce[:]); err != nil { 268 return head, nil, fmt.Errorf("can't get random data: %v", err) 269 } 270 c.headbuf.Reset() 271 binary.Write(&c.headbuf, binary.BigEndian, auth) 272 head.AuthData = c.headbuf.Bytes() 273 274 // Fill message ciphertext buffer with random bytes. 275 c.msgctbuf = append(c.msgctbuf[:0], make([]byte, randomPacketMsgSize)...) 276 crand.Read(c.msgctbuf) 277 return head, c.msgctbuf, nil 278 } 279 280 // encodeWhoareyou encodes a WHOAREYOU packet. 281 func (c *Codec) encodeWhoareyou(toID enode.ID, packet *Whoareyou) (Header, error) { 282 // Sanity check node field to catch misbehaving callers. 283 if packet.RecordSeq > 0 && packet.Node == nil { 284 panic("BUG: missing node in whoareyou with non-zero seq") 285 } 286 287 // Create header. 288 head := c.makeHeader(toID, flagWhoareyou, 0) 289 head.AuthData = bytesCopy(&c.buf) 290 head.Nonce = packet.Nonce 291 292 // Encode auth data. 293 auth := &whoareyouAuthData{ 294 IDNonce: packet.IDNonce, 295 RecordSeq: packet.RecordSeq, 296 } 297 c.headbuf.Reset() 298 binary.Write(&c.headbuf, binary.BigEndian, auth) 299 head.AuthData = c.headbuf.Bytes() 300 return head, nil 301 } 302 303 // encodeHandshakeMessage encodes the handshake message packet header. 304 func (c *Codec) encodeHandshakeHeader(toID enode.ID, addr string, challenge *Whoareyou) (Header, *session, error) { 305 // Ensure calling code sets challenge.node. 306 if challenge.Node == nil { 307 panic("BUG: missing challenge.Node in encode") 308 } 309 310 // Generate new secrets. 311 auth, session, err := c.makeHandshakeAuth(toID, addr, challenge) 312 if err != nil { 313 return Header{}, nil, err 314 } 315 316 // Generate nonce for message. 317 nonce, err := c.sc.nextNonce(session) 318 if err != nil { 319 return Header{}, nil, fmt.Errorf("can't generate nonce: %v", err) 320 } 321 322 // TODO: this should happen when the first authenticated message is received 323 c.sc.storeNewSession(toID, addr, session) 324 325 // Encode the auth header. 326 var ( 327 authsizeExtra = len(auth.pubkey) + len(auth.signature) + len(auth.record) 328 head = c.makeHeader(toID, flagHandshake, authsizeExtra) 329 ) 330 c.headbuf.Reset() 331 binary.Write(&c.headbuf, binary.BigEndian, &auth.h) 332 c.headbuf.Write(auth.signature) 333 c.headbuf.Write(auth.pubkey) 334 c.headbuf.Write(auth.record) 335 head.AuthData = c.headbuf.Bytes() 336 head.Nonce = nonce 337 return head, session, err 338 } 339 340 // encodeAuthHeader creates the auth header on a request packet following WHOAREYOU. 341 func (c *Codec) makeHandshakeAuth(toID enode.ID, addr string, challenge *Whoareyou) (*handshakeAuthData, *session, error) { 342 auth := new(handshakeAuthData) 343 auth.h.SrcID = c.localnode.ID() 344 345 // Create the ephemeral key. This needs to be first because the 346 // key is part of the ID nonce signature. 347 var remotePubkey = new(ecdsa.PublicKey) 348 if err := challenge.Node.Load((*enode.Secp256k1)(remotePubkey)); err != nil { 349 return nil, nil, fmt.Errorf("can't find secp256k1 key for recipient") 350 } 351 ephkey, err := c.sc.ephemeralKeyGen() 352 if err != nil { 353 return nil, nil, fmt.Errorf("can't generate ephemeral key") 354 } 355 ephpubkey := EncodePubkey(&ephkey.PublicKey) 356 auth.pubkey = ephpubkey[:] 357 auth.h.PubkeySize = byte(len(auth.pubkey)) 358 359 // Add ID nonce signature to response. 360 cdata := challenge.ChallengeData 361 idsig, err := makeIDSignature(c.sha256, c.privkey, cdata, ephpubkey[:], toID) 362 if err != nil { 363 return nil, nil, fmt.Errorf("can't sign: %v", err) 364 } 365 auth.signature = idsig 366 auth.h.SigSize = byte(len(auth.signature)) 367 368 // Add our record to response if it's newer than what remote side has. 369 ln := c.localnode.Node() 370 if challenge.RecordSeq < ln.Seq() { 371 auth.record, _ = rlp.EncodeToBytes(ln.Record()) 372 } 373 374 // Create session keys. 375 sec := deriveKeys(sha256.New, ephkey, remotePubkey, c.localnode.ID(), challenge.Node.ID(), cdata) 376 if sec == nil { 377 return nil, nil, fmt.Errorf("key derivation failed") 378 } 379 return auth, sec, err 380 } 381 382 // encodeMessage encodes an encrypted message packet. 383 func (c *Codec) encodeMessageHeader(toID enode.ID, s *session) (Header, error) { 384 head := c.makeHeader(toID, flagMessage, 0) 385 386 // Create the header. 387 nonce, err := c.sc.nextNonce(s) 388 if err != nil { 389 return Header{}, fmt.Errorf("can't generate nonce: %v", err) 390 } 391 auth := messageAuthData{SrcID: c.localnode.ID()} 392 c.buf.Reset() 393 binary.Write(&c.buf, binary.BigEndian, &auth) 394 head.AuthData = bytesCopy(&c.buf) 395 head.Nonce = nonce 396 return head, err 397 } 398 399 func (c *Codec) encryptMessage(s *session, p Packet, head *Header, headerData []byte) ([]byte, error) { 400 // Encode message plaintext. 401 c.msgbuf.Reset() 402 c.msgbuf.WriteByte(p.Kind()) 403 if err := rlp.Encode(&c.msgbuf, p); err != nil { 404 return nil, err 405 } 406 messagePT := c.msgbuf.Bytes() 407 408 // Encrypt into message ciphertext buffer. 409 messageCT, err := encryptGCM(c.msgctbuf[:0], s.writeKey, head.Nonce[:], messagePT, headerData) 410 if err == nil { 411 c.msgctbuf = messageCT 412 } 413 return messageCT, err 414 } 415 416 // Decode decodes a discovery packet. 417 func (c *Codec) Decode(input []byte, addr string) (src enode.ID, n *enode.Node, p Packet, err error) { 418 // Unmask the static header. 419 if len(input) < sizeofStaticPacketData { 420 return enode.ID{}, nil, nil, errTooShort 421 } 422 var head Header 423 copy(head.IV[:], input[:sizeofMaskingIV]) 424 mask := head.mask(c.localnode.ID()) 425 staticHeader := input[sizeofMaskingIV:sizeofStaticPacketData] 426 mask.XORKeyStream(staticHeader, staticHeader) 427 428 // Decode and verify the static header. 429 c.reader.Reset(staticHeader) 430 binary.Read(&c.reader, binary.BigEndian, &head.StaticHeader) 431 remainingInput := len(input) - sizeofStaticPacketData 432 if err := head.checkValid(remainingInput); err != nil { 433 return enode.ID{}, nil, nil, err 434 } 435 436 // Unmask auth data. 437 authDataEnd := sizeofStaticPacketData + int(head.AuthSize) 438 authData := input[sizeofStaticPacketData:authDataEnd] 439 mask.XORKeyStream(authData, authData) 440 head.AuthData = authData 441 442 // Delete timed-out handshakes. This must happen before decoding to avoid 443 // processing the same handshake twice. 444 c.sc.handshakeGC() 445 446 // Decode auth part and message. 447 headerData := input[:authDataEnd] 448 msgData := input[authDataEnd:] 449 switch head.Flag { 450 case flagWhoareyou: 451 p, err = c.decodeWhoareyou(&head, headerData) 452 case flagHandshake: 453 n, p, err = c.decodeHandshakeMessage(addr, &head, headerData, msgData) 454 case flagMessage: 455 p, err = c.decodeMessage(addr, &head, headerData, msgData) 456 default: 457 err = errInvalidFlag 458 } 459 return head.src, n, p, err 460 } 461 462 // decodeWhoareyou reads packet data after the header as a WHOAREYOU packet. 463 func (c *Codec) decodeWhoareyou(head *Header, headerData []byte) (Packet, error) { 464 if len(head.AuthData) != sizeofWhoareyouAuthData { 465 return nil, fmt.Errorf("invalid auth size %d for WHOAREYOU", len(head.AuthData)) 466 } 467 var auth whoareyouAuthData 468 c.reader.Reset(head.AuthData) 469 binary.Read(&c.reader, binary.BigEndian, &auth) 470 p := &Whoareyou{ 471 Nonce: head.Nonce, 472 IDNonce: auth.IDNonce, 473 RecordSeq: auth.RecordSeq, 474 ChallengeData: make([]byte, len(headerData)), 475 } 476 copy(p.ChallengeData, headerData) 477 return p, nil 478 } 479 480 func (c *Codec) decodeHandshakeMessage(fromAddr string, head *Header, headerData, msgData []byte) (n *enode.Node, p Packet, err error) { 481 node, auth, session, err := c.decodeHandshake(fromAddr, head) 482 if err != nil { 483 c.sc.deleteHandshake(auth.h.SrcID, fromAddr) 484 return nil, nil, err 485 } 486 487 // Decrypt the message using the new session keys. 488 msg, err := c.decryptMessage(msgData, head.Nonce[:], headerData, session.readKey) 489 if err != nil { 490 c.sc.deleteHandshake(auth.h.SrcID, fromAddr) 491 return node, msg, err 492 } 493 494 // Handshake OK, drop the challenge and store the new session keys. 495 c.sc.storeNewSession(auth.h.SrcID, fromAddr, session) 496 c.sc.deleteHandshake(auth.h.SrcID, fromAddr) 497 return node, msg, nil 498 } 499 500 func (c *Codec) decodeHandshake(fromAddr string, head *Header) (n *enode.Node, auth handshakeAuthData, s *session, err error) { 501 if auth, err = c.decodeHandshakeAuthData(head); err != nil { 502 return nil, auth, nil, err 503 } 504 505 // Verify against our last WHOAREYOU. 506 challenge := c.sc.getHandshake(auth.h.SrcID, fromAddr) 507 if challenge == nil { 508 return nil, auth, nil, errUnexpectedHandshake 509 } 510 // Get node record. 511 n, err = c.decodeHandshakeRecord(challenge.Node, auth.h.SrcID, auth.record) 512 if err != nil { 513 return nil, auth, nil, err 514 } 515 // Verify ID nonce signature. 516 sig := auth.signature 517 cdata := challenge.ChallengeData 518 err = verifyIDSignature(c.sha256, sig, n, cdata, auth.pubkey, c.localnode.ID()) 519 if err != nil { 520 return nil, auth, nil, err 521 } 522 // Verify ephemeral key is on curve. 523 ephkey, err := DecodePubkey(c.privkey.Curve, auth.pubkey) 524 if err != nil { 525 return nil, auth, nil, errInvalidAuthKey 526 } 527 // Derive sesssion keys. 528 session := deriveKeys(sha256.New, c.privkey, ephkey, auth.h.SrcID, c.localnode.ID(), cdata) 529 session = session.keysFlipped() 530 return n, auth, session, nil 531 } 532 533 // decodeHandshakeAuthData reads the authdata section of a handshake packet. 534 func (c *Codec) decodeHandshakeAuthData(head *Header) (auth handshakeAuthData, err error) { 535 // Decode fixed size part. 536 if len(head.AuthData) < sizeofHandshakeAuthData { 537 return auth, fmt.Errorf("header authsize %d too low for handshake", head.AuthSize) 538 } 539 c.reader.Reset(head.AuthData) 540 binary.Read(&c.reader, binary.BigEndian, &auth.h) 541 head.src = auth.h.SrcID 542 543 // Decode variable-size part. 544 var ( 545 vardata = head.AuthData[sizeofHandshakeAuthData:] 546 sigAndKeySize = int(auth.h.SigSize) + int(auth.h.PubkeySize) 547 keyOffset = int(auth.h.SigSize) 548 recOffset = keyOffset + int(auth.h.PubkeySize) 549 ) 550 if len(vardata) < sigAndKeySize { 551 return auth, errTooShort 552 } 553 auth.signature = vardata[:keyOffset] 554 auth.pubkey = vardata[keyOffset:recOffset] 555 auth.record = vardata[recOffset:] 556 return auth, nil 557 } 558 559 // decodeHandshakeRecord verifies the node record contained in a handshake packet. The 560 // remote node should include the record if we don't have one or if ours is older than the 561 // latest sequence number. 562 func (c *Codec) decodeHandshakeRecord(local *enode.Node, wantID enode.ID, remote []byte) (*enode.Node, error) { 563 node := local 564 if len(remote) > 0 { 565 var record enr.Record 566 if err := rlp.DecodeBytes(remote, &record); err != nil { 567 return nil, err 568 } 569 if local == nil || local.Seq() < record.Seq() { 570 n, err := enode.New(enode.ValidSchemes, &record) 571 if err != nil { 572 return nil, fmt.Errorf("invalid node record: %v", err) 573 } 574 if n.ID() != wantID { 575 return nil, fmt.Errorf("record in handshake has wrong ID: %v", n.ID()) 576 } 577 node = n 578 } 579 } 580 if node == nil { 581 return nil, errNoRecord 582 } 583 return node, nil 584 } 585 586 // decodeMessage reads packet data following the header as an ordinary message packet. 587 func (c *Codec) decodeMessage(fromAddr string, head *Header, headerData, msgData []byte) (Packet, error) { 588 if len(head.AuthData) != sizeofMessageAuthData { 589 return nil, fmt.Errorf("invalid auth size %d for message packet", len(head.AuthData)) 590 } 591 var auth messageAuthData 592 c.reader.Reset(head.AuthData) 593 binary.Read(&c.reader, binary.BigEndian, &auth) 594 head.src = auth.SrcID 595 596 // Try decrypting the message. 597 key := c.sc.readKey(auth.SrcID, fromAddr) 598 msg, err := c.decryptMessage(msgData, head.Nonce[:], headerData, key) 599 if err == errMessageDecrypt { 600 // It didn't work. Start the handshake since this is an ordinary message packet. 601 return &Unknown{Nonce: head.Nonce}, nil 602 } 603 return msg, err 604 } 605 606 func (c *Codec) decryptMessage(input, nonce, headerData, readKey []byte) (Packet, error) { 607 msgdata, err := decryptGCM(readKey, nonce, input, headerData) 608 if err != nil { 609 return nil, errMessageDecrypt 610 } 611 if len(msgdata) == 0 { 612 return nil, errMessageTooShort 613 } 614 return DecodeMessage(msgdata[0], msgdata[1:]) 615 } 616 617 // checkValid performs some basic validity checks on the header. 618 // The packetLen here is the length remaining after the static header. 619 func (h *StaticHeader) checkValid(packetLen int) error { 620 if h.ProtocolID != protocolID { 621 return errInvalidHeader 622 } 623 if h.Version < minVersion { 624 return errMinVersion 625 } 626 if h.Flag != flagWhoareyou && packetLen < minMessageSize { 627 return errMsgTooShort 628 } 629 if int(h.AuthSize) > packetLen { 630 return errAuthSize 631 } 632 return nil 633 } 634 635 // headerMask returns a cipher for 'masking' / 'unmasking' packet headers. 636 func (h *Header) mask(destID enode.ID) cipher.Stream { 637 block, err := aes.NewCipher(destID[:16]) 638 if err != nil { 639 panic("can't create cipher") 640 } 641 return cipher.NewCTR(block, h.IV[:]) 642 } 643 644 func bytesCopy(r *bytes.Buffer) []byte { 645 b := make([]byte, r.Len()) 646 copy(b, r.Bytes()) 647 return b 648 }