ddn.net.ssh.packet_chacha

OpenSSH chacha20-poly1305@openssh.com packet protection.

This is the OpenSSH construction from PROTOCOL.chacha20poly1305, not the RFC 8439 AEAD: 64-byte key material splits into K_2 (first 32 bytes, payload) and K_1 (second 32 bytes, packet length); the Poly1305 key is the first 256 bits of the K_2 stream at block counter zero; the payload is encrypted with K_2 from block counter one; the tag covers the encrypted length and encrypted payload together. The nonce is the 64-bit packet sequence number in SSH wire (big-endian) encoding.

Types 4

classSshChaChaException : Exception

Raised for packet violations: bad lengths, padding, authentication failures, or sequence exhaustion.

Constructors
this(string msg, string file = __FILE__, size_t line = __LINE__)Constructs a packet-protection exception.

Framing parameters of the OpenSSH construction.

blockSize = 8ChaCha20 block size; the packet body aligns to this
tagSize = 16Poly1305 tag length
keySize = 64Full key material length (K_2 then K_1)
lengthSize = 4Encrypted length field size

OpenSSH ChaCha20-Poly1305 packet writer.

Produces encrypted-length || encrypted-payload || tag wire packets with a fresh key/nonce derivation per packet.

Fields
private ubyte[64] key_
private CryptoRandom rng_
private uint sequenceNumber_
private bool sequenceExhausted_
private bool wiped_
Methods
uint sequenceNumber() @property const pure nothrow @nogcReturns: the sequence number of the next packet to be written.
void wipe() nothrow @nogc @trustedVolatile-wipes the long-lived ChaCha20 key material.
void setSequence(uint value) pure nothrow @nogc @safeSets the sequence number explicitly (continuity across rekey).
ubyte[] protect(const(ubyte)[] payload)Encrypts and authenticates one payload.
private ubyte[] computeTag(const(ubyte)[] tagKey, const(ubyte)[] encryptedLength, const(ubyte)[] encryptedBody) static
Constructors
this(const(ubyte)[] key, CryptoRandom rng)Constructs a writer from the 64-byte derived key material.

OpenSSH ChaCha20-Poly1305 packet reader.

Decrypts the announced length first (K_1, counter zero) and bounds it before further buffering, then verifies the tag over the ciphertext before any payload decryption.

Fields
private ubyte[64] key_
private ubyte[] buffer_
private ulong announcedLength_
private bool lengthDecoded_
private uint sequenceNumber_
private bool sequenceExhausted_
private bool wiped_
Methods
uint sequenceNumber() @property const pure nothrow @nogcReturns: the sequence number of the next packet to be read.
void wipe() nothrow @nogc @trustedVolatile-wipes the long-lived key and buffered wire data.
void setSequence(uint value) pure nothrow @nogc @safeSets the sequence number explicitly (continuity across rekey).
size_t bytesNeeded() @property const pure nothrow @nogc @safeReturns: how many more wire bytes the current packet still needs, or 0 when a full packet is buffered.
bool packetReady() @property const pure nothrow @nogc @safeReturns: whether a complete packet is buffered.
void feed(const(ubyte)[] data) @safeFeeds received wire bytes.
private void decodeLengthIfPossible() @trusted
ubyte[] take()Takes the next authenticated packet's payload.
Constructors
this(const(ubyte)[] key)Constructs a reader from the 64-byte derived key material.

Functions 3

private fnubyte[] chachaCrypt(const(ubyte)[] key, in ubyte[8] nonce, ulong blockCounter, const(ubyte)[] input) @trusted
private fnvoid advanceSequence(ref uint sequenceNumber, ref bool exhausted) pure nothrow @nogc @safe
private fnubyte[8] sequenceNonce(uint sequenceNumber) pure nothrow @nogc @safe