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