pub mod chacha20 {
use chacha20::cipher::{KeyIvInit, StreamCipherCore, StreamCipherSeekCore};
pub const NONCE_BYTES: usize = 8;
pub const KEY_BYTES: usize = 32;
pub struct Nonce(pub [u8; NONCE_BYTES]);
pub struct Key(pub [u8; KEY_BYTES]);
pub fn chacha20_xor(c: &mut [u8], n: &Nonce, k: &Key) {
let res = chacha20::ChaCha20LegacyCore::new(&k.0.into(), &n.0.into());
chacha20::ChaCha20LegacyCore::apply_keystream_partial(res, c.into());
}
pub fn chacha20_xor_ic(c: &mut [u8], n: &Nonce, ic: u64, k: &Key) {
let mut res = chacha20::ChaCha20LegacyCore::new(&k.0.into(), &n.0.into());
chacha20::ChaCha20LegacyCore::set_block_pos(&mut res, ic as u32);
chacha20::ChaCha20LegacyCore::apply_keystream_partial(res, c.into());
}
}
pub mod poly1305 {
use chacha20::cipher::KeyInit;
use poly1305 as poly;
use subtle::ConstantTimeEq;
pub const KEY_BYTES: usize = 32;
pub const TAG_BYTES: usize = 16;
pub struct Key(pub [u8; KEY_BYTES]);
pub struct Tag(pub [u8; TAG_BYTES]);
pub fn poly1305_auth(m: &[u8], key: &Key) -> Tag {
Tag(poly::Poly1305::new(&key.0.into())
.compute_unpadded(m)
.into())
}
pub fn poly1305_verify(tag: &[u8], m: &[u8], key: &Key) -> bool {
let t: [u8; TAG_BYTES] = poly::Poly1305::new(&key.0.into())
.compute_unpadded(m)
.into();
From::from(t.ct_eq(tag))
}
}
pub mod ed25519 {
use ed25519_dalek::ed25519::signature::Signer;
pub const PUBLICKEY_BYTES: usize = 32;
pub const SECRETKEY_BYTES: usize = 64;
pub const SIGNATURE_BYTES: usize = 64;
/// Ed25519 public key.
#[derive(Debug, PartialEq, Eq)]
pub struct PublicKey {
/// Actual key
pub key: [u8; PUBLICKEY_BYTES],
}
impl PublicKey {
pub fn new_zeroed() -> Self {
PublicKey {
key: [0; PUBLICKEY_BYTES],
}
}
}
/// Ed25519 secret key.
#[derive(Clone)]
pub struct SecretKey {
/// Actual key
pub key: [u8; SECRETKEY_BYTES],
}
impl SecretKey {
pub fn new_zeroed() -> Self {
SecretKey {
key: [0; SECRETKEY_BYTES],
}
}
}
pub struct Signature(pub [u8; SIGNATURE_BYTES]);
/// Generate a key pair.
pub fn keypair() -> (PublicKey, SecretKey) {
let mut pk = PublicKey {
key: [0; PUBLICKEY_BYTES],
};
let mut sk = SecretKey {
key: [0; SECRETKEY_BYTES],
};
let mut csprng = rand::rngs::OsRng;
let signing = ed25519_dalek::SigningKey::generate(&mut csprng);
sk.key.copy_from_slice(&signing.to_keypair_bytes());
pk.key.copy_from_slice(signing.verifying_key().as_bytes());
(pk, sk)
}
/// Verify a signature, `sig` could as well be a `Signature`.
pub fn verify_detached(sig: &[u8], m: &[u8], pk: &PublicKey) -> bool {
if let Ok(sig) = ed25519_dalek::Signature::from_slice(sig) {
if let Ok(pk) = ed25519_dalek::VerifyingKey::from_bytes(&pk.key) {
pk.verify_strict(m, &sig).is_ok()
} else {
false
}
} else {
false
}
}
/// Sign a message with a secret key.
pub fn sign_detached(m: &[u8], sk: &SecretKey) -> Signature {
if let Ok(sk) = ed25519_dalek::SigningKey::from_keypair_bytes(&sk.key) {
Signature(sk.sign(m).to_bytes())
} else {
Signature([0; SIGNATURE_BYTES])
}
}
}
pub mod scalarmult {
pub const BYTES: usize = 32;
pub use x25519_dalek::PublicKey;
pub use x25519_dalek::ReusableSecret;
pub use x25519_dalek::SharedSecret;
#[derive(Debug)]
pub struct GroupElement(pub [u8; BYTES]);
pub fn scalarmult_base(n: &ReusableSecret) -> PublicKey {
x25519_dalek::PublicKey::from(n)
}
pub fn scalarmult(n: &ReusableSecret, p: &PublicKey) -> SharedSecret {
n.diffie_hellman(p)
}
}