DecryptWithCachedCrypto decrypts an Initial packet using pre-derived keys. This is faster than decryptInitialPacket as it reuses cipher objects. Uses buffer pool to avoid per-packet allocations.
(packet, encrypted []byte, hpCipher cipher.Block, aead cipher.AEAD, iv []byte)
| 462 | // This is faster than decryptInitialPacket as it reuses cipher objects. |
| 463 | // Uses buffer pool to avoid per-packet allocations. |
| 464 | func DecryptWithCachedCrypto(packet, encrypted []byte, |
| 465 | hpCipher cipher.Block, aead cipher.AEAD, iv []byte) ([]byte, error) { |
| 466 | |
| 467 | if len(encrypted) < 20 { |
| 468 | return nil, errors.New("encrypted payload too short") |
| 469 | } |
| 470 | |
| 471 | // Sample starts at 4 bytes into the payload (after packet number) |
| 472 | sample := encrypted[4:20] |
| 473 | var mask [16]byte // Stack allocation |
| 474 | hpCipher.Encrypt(mask[:], sample) |
| 475 | |
| 476 | // Get buffer from pool for packet copy (avoids allocation) |
| 477 | bufPtr := handler.GetBuffer() |
| 478 | defer handler.PutBuffer(bufPtr) |
| 479 | packetCopy := (*bufPtr)[:len(packet)] |
| 480 | copy(packetCopy, packet) |
| 481 | |
| 482 | // Remove header protection from first byte |
| 483 | if packetCopy[0]&0x80 == 0x80 { |
| 484 | packetCopy[0] ^= mask[0] & 0x0f |
| 485 | } else { |
| 486 | packetCopy[0] ^= mask[0] & 0x1f |
| 487 | } |
| 488 | |
| 489 | // Determine packet number length |
| 490 | pnLen := (packetCopy[0] & 0x03) + 1 |
| 491 | |
| 492 | // Find packet number offset (need to recalculate) |
| 493 | pnOffset := len(packet) - len(encrypted) |
| 494 | |
| 495 | // Remove header protection from packet number |
| 496 | for i := 0; i < int(pnLen); i++ { |
| 497 | packetCopy[pnOffset+i] ^= mask[1+i] |
| 498 | } |
| 499 | |
| 500 | // Read packet number |
| 501 | var pn uint64 |
| 502 | for i := 0; i < int(pnLen); i++ { |
| 503 | pn = (pn << 8) | uint64(packetCopy[pnOffset+i]) |
| 504 | } |
| 505 | |
| 506 | // Create nonce (stack allocation) |
| 507 | var nonce [12]byte |
| 508 | copy(nonce[:], iv) |
| 509 | for i := 0; i < 8; i++ { |
| 510 | nonce[4+i] ^= byte(pn >> (56 - 8*i)) |
| 511 | } |
| 512 | |
| 513 | // Decrypt |
| 514 | ciphertext := encrypted[pnLen:] |
| 515 | aad := packetCopy[:pnOffset+int(pnLen)] // Associated data is the header |
| 516 | |
| 517 | plaintext, err := aead.Open(nil, nonce[:], ciphertext, aad) |
| 518 | if err != nil { |
| 519 | return nil, fmt.Errorf("decryption failed: %w", err) |
| 520 | } |
| 521 |
no test coverage detected