pub struct ChaCha20Poly1305 { /* private fields */ }Available on crate feature
chacha20poly1305 only.Expand description
OpenSSH variant of ChaCha20Poly1305: chacha20-poly1305@openssh.com as described in
PROTOCOL.chacha20poly1305.
Differences from ChaCha20Poly1305-IETF as described in RFC8439:
- Nonce is 64-bit instead of 96-bit (i.e. uses legacy “djb” ChaCha20 variant).
- The AAD and ciphertext inputs of Poly1305 are not padded.
- The lengths of ciphertext and AAD are not authenticated using Poly1305.
- Maximum supported AAD size is 16.
§Usage notes
- In the context of SSH packet encryption, AAD will be 4 bytes and contain the encrypted length.
- In the context of SSH key encryption, AAD will be empty.
§Implementing packet encryption
The ChaCha20Poly1305 type implements just the AEAD primitive used by OpenSSH, and takes
a 32-byte/256-bit key. However, the full construction used for packet encryption requires
64-byte/512-bit keys, which are split into two 32-byte/256-bit keys (K_1 and K_2), where
K_1 is used for length encryption, and K_2 for the packet body in addition to authenticating
the ciphertext encrypted under K_1.
§Packet encryption example
use ssh_cipher::{
ChaCha20, ChaCha20Poly1305, ChaChaKey, ChaChaNonce, Tag,
aead::{AeadInOut, KeyInit},
cipher::{KeyIvInit, StreamCipher},
};
fn encrypt_packet(
key: &[u8; 64],
seq_num: u32,
packet: &mut [u8],
) -> Result<([u8; 4], Tag), aead::Error> {
let (k1, k2) = split_key(key);
let mut nonce = ChaChaNonce::default();
nonce[4..].copy_from_slice(&seq_num.to_be_bytes());
// Encrypt 4-byte packet length under `K_1` using raw `ChaCha20`.
let packet_len = u32::try_from(packet.len()).map_err(|_| aead::Error)?;
let mut len_bytes = packet_len.to_be_bytes();
let mut len_cipher = ChaCha20::new(&k1, &nonce);
len_cipher.apply_keystream(&mut len_bytes);
// Encrypt packet body while authenticating encrypted `len_ct` as AAD.
let body_cipher = ChaCha20Poly1305::new(&k2);
let tag = body_cipher.encrypt_inout_detached(&nonce, &len_bytes, packet.into())?;
Ok((len_bytes, tag))
}
fn decrypt_packet(
key: &[u8; 64],
seq_num: u32,
mut enc_len: [u8; 4],
packet: &mut [u8],
tag: &Tag,
) -> Result<u32, aead::Error> {
let (k1, k2) = split_key(key);
let mut nonce = ChaChaNonce::default();
nonce[4..].copy_from_slice(&seq_num.to_be_bytes());
// Authenticate length and decrypt body
let aead = ChaCha20Poly1305::new(&k2);
aead.decrypt_inout_detached(&nonce, &enc_len, packet.into(), tag)?;
// If ciphertext is authentic, decrypt the length
let mut len_cipher = ChaCha20::new(&k2, &nonce);
len_cipher.apply_keystream(&mut enc_len);
Ok(u32::from_be_bytes(enc_len))
}
// Split 512-bit key into `K_1` and `K_2`
fn split_key(key: &[u8; 64]) -> (ChaChaKey, ChaChaKey) {
let (k1, k2) = key.split_at(32);
(ChaChaKey::try_from(k1).unwrap(), ChaChaKey::try_from(k2).unwrap())
}Trait Implementations§
Source§impl AeadCore for ChaCha20Poly1305
impl AeadCore for ChaCha20Poly1305
Source§impl AeadInOut for ChaCha20Poly1305
impl AeadInOut for ChaCha20Poly1305
Source§fn encrypt_inout_detached(
&self,
nonce: &ChaChaNonce,
associated_data: &[u8],
buffer: InOutBuf<'_, '_, u8>,
) -> Result<Tag>
fn encrypt_inout_detached( &self, nonce: &ChaChaNonce, associated_data: &[u8], buffer: InOutBuf<'_, '_, u8>, ) -> Result<Tag>
Source§fn decrypt_inout_detached(
&self,
nonce: &ChaChaNonce,
associated_data: &[u8],
buffer: InOutBuf<'_, '_, u8>,
tag: &Tag,
) -> Result<()>
fn decrypt_inout_detached( &self, nonce: &ChaChaNonce, associated_data: &[u8], buffer: InOutBuf<'_, '_, u8>, tag: &Tag, ) -> Result<()>
Source§impl Clone for ChaCha20Poly1305
impl Clone for ChaCha20Poly1305
Source§fn clone(&self) -> ChaCha20Poly1305
fn clone(&self) -> ChaCha20Poly1305
Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreSource§impl Debug for ChaCha20Poly1305
impl Debug for ChaCha20Poly1305
Source§impl Drop for ChaCha20Poly1305
impl Drop for ChaCha20Poly1305
Source§impl KeyInit for ChaCha20Poly1305
impl KeyInit for ChaCha20Poly1305
Source§fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength>
fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength>
Create new value from variable size key. Read more
Source§impl KeySizeUser for ChaCha20Poly1305
impl KeySizeUser for ChaCha20Poly1305
impl ZeroizeOnDrop for ChaCha20Poly1305
Available on crate feature
zeroize only.Auto Trait Implementations§
impl Freeze for ChaCha20Poly1305
impl RefUnwindSafe for ChaCha20Poly1305
impl Send for ChaCha20Poly1305
impl Sync for ChaCha20Poly1305
impl Unpin for ChaCha20Poly1305
impl UnsafeUnpin for ChaCha20Poly1305
impl UnwindSafe for ChaCha20Poly1305
Blanket Implementations§
Source§impl<T> AeadInPlace for Twhere
T: AeadInOut,
impl<T> AeadInPlace for Twhere
T: AeadInOut,
Source§fn encrypt_in_place(
&self,
nonce: &Array<u8, <T as AeadCore>::NonceSize>,
associated_data: &[u8],
buffer: &mut dyn Buffer,
) -> Result<(), Error>
fn encrypt_in_place( &self, nonce: &Array<u8, <T as AeadCore>::NonceSize>, associated_data: &[u8], buffer: &mut dyn Buffer, ) -> Result<(), Error>
👎Deprecated since 0.6.0:
use AeadInOut::encrypt_in_place instead
Encrypt the given buffer containing a plaintext message in-place.
Source§fn encrypt_in_place_detached(
&self,
nonce: &Array<u8, <T as AeadCore>::NonceSize>,
associated_data: &[u8],
buffer: &mut [u8],
) -> Result<Array<u8, <T as AeadCore>::TagSize>, Error>
fn encrypt_in_place_detached( &self, nonce: &Array<u8, <T as AeadCore>::NonceSize>, associated_data: &[u8], buffer: &mut [u8], ) -> Result<Array<u8, <T as AeadCore>::TagSize>, Error>
👎Deprecated since 0.6.0:
use AeadInOut::encrypt_inout_detached instead
Encrypt the data in-place, returning the authentication tag
Source§fn decrypt_in_place(
&self,
nonce: &Array<u8, <T as AeadCore>::NonceSize>,
associated_data: &[u8],
buffer: &mut dyn Buffer,
) -> Result<(), Error>
fn decrypt_in_place( &self, nonce: &Array<u8, <T as AeadCore>::NonceSize>, associated_data: &[u8], buffer: &mut dyn Buffer, ) -> Result<(), Error>
👎Deprecated since 0.6.0:
use AeadInOut::decrypt_in_place instead
Decrypt the message in-place, returning an error in the event the
provided authentication tag does not match the given ciphertext.
Source§fn decrypt_in_place_detached(
&self,
nonce: &Array<u8, <T as AeadCore>::NonceSize>,
associated_data: &[u8],
buffer: &mut [u8],
tag: &Array<u8, <T as AeadCore>::TagSize>,
) -> Result<(), Error>
fn decrypt_in_place_detached( &self, nonce: &Array<u8, <T as AeadCore>::NonceSize>, associated_data: &[u8], buffer: &mut [u8], tag: &Array<u8, <T as AeadCore>::TagSize>, ) -> Result<(), Error>
👎Deprecated since 0.6.0:
use AeadInOut::decrypt_inout_detached instead
Decrypt the message in-place, returning an error in the event the provided
authentication tag does not match the given ciphertext (i.e. ciphertext
is modified/unauthentic)
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more