=pod

=encoding utf-8

=head1 NAME

Noise::SymmetricState - Cryptographic transcript and chaining key management

=head1 SYNOPSIS

    use Noise::SymmetricState;

    my $state = Noise::SymmetricState->new(
        hash   => 'SHA256',
        cipher => 'ChaChaPoly'
    );

    $state->initialize_symmetric( 'Noise_XX_25519_ChaChaPoly_SHA256' );
    $state->mix_hash( $some_data );
    $state->mix_key( $shared_secret );

    my $ct = $state->encrypt_and_hash( $plaintext );

=head1 DESCRIPTION

Noise::SymmetricState manages the two primary variables of a Noise handshake: the handshake hash (C<h>) and the
chaining key (C<ck>).

It ensures that all messages sent or received are incorporated into the transcript and that encryption keys are derived
correctly according to the Noise specification.

=head1 METHODS

=head2 C<new( %params )>

Constructor.

Expected parameters:

=over

=item C<hash>: 'SHA256' or 'SHA512'.

=item C<cipher>: 'ChaChaPoly' or 'AESGCM'.

=back

=head2 C<initialize_symmetric( $protocol_name )>

Sets the initial values for C<h> and C<ck> based on the full protocol name.

=head2 C<mix_key( $ikm )>

Updates the chaining key and derives a new symmetric encryption key using HKDF with the provided Input Keying Material.

=head2 C<mix_hash( $data )>

Updates the handshake hash C<h> by hashing it with C<$data>.

=head2 C<mix_key_and_hash( $ikm )>

A specialized version of key and hash mixing used primarily for pre-shared keys (PSKs).

=head2 C<encrypt_and_hash( $plaintext )>

Encrypts C<$plaintext> using the internal L<Noise::CipherState> and then incorporates the resulting ciphertext into the
handshake hash.

=head2 C<decrypt_and_hash( $ciphertext )>

Decrypts C<$ciphertext> and incorporates it into the handshake hash.

=head2 C<split( )>

Finalizes the handshake phase. Returns two L<Noise::CipherState> objects, one for each direction of communication.

=head2 C<h( )>

Returns the current handshake hash. This is a running hash of everything that has been sent or received so far in the
handshake. It is used as associated data for all encryption/decryption within the handshake to ensure the integrity of
the entire transcript.

=head2 C<ck( )>

Returns the current chaining key. The chaining key is used to derive new keys (via HKDF) whenever a Diffie-Hellman
exchange occurs. It ensures that future keys are cryptographically linked to all previous secrets.

=head2 C<cipher_state( )>

Returns the underlying L<Noise::CipherState> object. This object manages the encryption key derived from the chaining
key and handles the actual symmetric cryptographic operations.

=head1 SEE ALSO

L<Noise::CipherState>, L<Noise::HandshakeState>

=head1 AUTHOR

Sanko Robinson E<lt>sanko@cpan.orgE<gt>

=head1 COPYRIGHT

Copyright (C) 2026 by Sanko Robinson.

This library is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0.

=cut
