use crate::{
crypto::dsa::{DsaPublicKey, DsaSignature},
error::Error,
};
use data_encoding::{Encoding, Specification};
use ed25519_dalek::Signer;
use lazy_static::lazy_static;
use p256::ecdsa::signature::Verifier as _;
use rand::rand_core::CryptoRng;
use zeroize::Zeroize;
use alloc::{string::String, vec::Vec};
use core::convert::TryInto;
pub mod aes;
pub mod chachapoly;
pub mod dsa;
pub mod hmac;
pub mod noise;
pub mod sha256;
pub mod siphash;
lazy_static! {
pub static ref I2P_BASE64: Encoding = {
let mut spec = Specification::new();
spec.symbols
.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~");
spec.padding = Some('=');
spec.encoding().unwrap()
};
pub static ref I2P_BASE32: Encoding = {
let mut spec = Specification::new();
spec.symbols.push_str("abcdefghijklmnopqrstuvwxyz234567");
spec.encoding().unwrap()
};
}
pub fn base64_encode<T: AsRef<[u8]>>(data: T) -> String {
I2P_BASE64.encode(data.as_ref())
}
pub fn base64_decode<T: AsRef<[u8]>>(data: T) -> Option<Vec<u8>> {
I2P_BASE64.decode(data.as_ref()).ok()
}
pub fn base32_encode(data: impl AsRef<[u8]>) -> String {
I2P_BASE32.encode(data.as_ref())
}
#[allow(unused)]
pub fn base32_decode(data: impl AsRef<[u8]>) -> Option<Vec<u8>> {
I2P_BASE32.decode(data.as_ref()).ok()
}
pub trait SecretKey {
fn diffie_hellman<T: AsRef<x25519_dalek::PublicKey>>(&self, public_key: &T) -> [u8; 32];
}
pub enum SigningKeyKind {
DsaSha1(usize),
EcDsaSha256P256(usize),
EdDsaSha512Ed25519(usize),
}
impl TryFrom<u16> for SigningKeyKind {
type Error = ();
fn try_from(value: u16) -> Result<Self, Self::Error> {
match value {
0 => Ok(SigningKeyKind::DsaSha1(128)),
1 => Ok(SigningKeyKind::EcDsaSha256P256(64)),
7 => Ok(SigningKeyKind::EdDsaSha512Ed25519(32)),
_ => Err(()),
}
}
}
pub enum PrivateKeyKind {
ElGamal(usize),
P256(usize),
X25519(usize),
}
impl TryFrom<u16> for PrivateKeyKind {
type Error = ();
fn try_from(value: u16) -> Result<Self, Self::Error> {
match value {
0 => Ok(PrivateKeyKind::ElGamal(256)),
1 => Ok(PrivateKeyKind::P256(64)),
4 => Ok(PrivateKeyKind::X25519(32)),
_ => Err(()),
}
}
}
#[derive(Debug, Clone)]
pub enum StaticPublicKey {
X25519(x25519_dalek::PublicKey),
MlKem512X25519(x25519_dalek::PublicKey),
MlKem768X25519(x25519_dalek::PublicKey),
MlKem1024X25519(x25519_dalek::PublicKey),
}
impl StaticPublicKey {
pub fn from_bytes(bytes: [u8; 32]) -> Self {
Self::X25519(x25519_dalek::PublicKey::from(bytes))
}
pub fn from_bytes_ml_kem_512(bytes: [u8; 32]) -> Self {
Self::MlKem512X25519(x25519_dalek::PublicKey::from(bytes))
}
pub fn from_bytes_ml_kem_768(bytes: [u8; 32]) -> Self {
Self::MlKem768X25519(x25519_dalek::PublicKey::from(bytes))
}
pub fn from_bytes_ml_kem_1024(bytes: [u8; 32]) -> Self {
Self::MlKem1024X25519(x25519_dalek::PublicKey::from(bytes))
}
pub fn try_from_bytes(bytes: &[u8]) -> Option<Self> {
let key: [u8; 32] = bytes.try_into().ok()?;
Some(Self::X25519(x25519_dalek::PublicKey::from(key)))
}
pub fn try_from_bytes_ml_kem_512(bytes: &[u8]) -> Option<Self> {
let key: [u8; 32] = bytes.try_into().ok()?;
Some(Self::MlKem512X25519(x25519_dalek::PublicKey::from(key)))
}
pub fn try_from_bytes_ml_kem_768(bytes: &[u8]) -> Option<Self> {
let key: [u8; 32] = bytes.try_into().ok()?;
Some(Self::MlKem768X25519(x25519_dalek::PublicKey::from(key)))
}
pub fn try_from_bytes_ml_kem_1024(bytes: &[u8]) -> Option<Self> {
let key: [u8; 32] = bytes.try_into().ok()?;
Some(Self::MlKem1024X25519(x25519_dalek::PublicKey::from(key)))
}
pub fn to_vec(&self) -> Vec<u8> {
match self {
Self::X25519(key) => key.to_bytes().to_vec(),
Self::MlKem512X25519(key) => key.to_bytes().to_vec(),
Self::MlKem768X25519(key) => key.to_bytes().to_vec(),
Self::MlKem1024X25519(key) => key.to_bytes().to_vec(),
}
}
}
impl AsRef<[u8]> for StaticPublicKey {
fn as_ref(&self) -> &[u8] {
match self {
Self::X25519(key) => key.as_ref(),
Self::MlKem512X25519(key) => key.as_ref(),
Self::MlKem768X25519(key) => key.as_ref(),
Self::MlKem1024X25519(key) => key.as_ref(),
}
}
}
impl AsRef<x25519_dalek::PublicKey> for StaticPublicKey {
fn as_ref(&self) -> &x25519_dalek::PublicKey {
match self {
Self::X25519(key) => key,
Self::MlKem512X25519(key) => key,
Self::MlKem768X25519(key) => key,
Self::MlKem1024X25519(key) => key,
}
}
}
#[derive(Clone)]
pub enum StaticPrivateKey {
X25519(x25519_dalek::StaticSecret),
MlKem512X25519(x25519_dalek::StaticSecret),
MlKem768X25519(x25519_dalek::StaticSecret),
MlKem1024X25519(x25519_dalek::StaticSecret),
}
impl StaticPrivateKey {
pub fn random(mut csprng: impl CryptoRng) -> Self {
Self::X25519(x25519_dalek::StaticSecret::random_from_rng(&mut csprng))
}
pub fn random_ml_kem_512(mut csprng: impl CryptoRng) -> Self {
Self::MlKem512X25519(x25519_dalek::StaticSecret::random_from_rng(&mut csprng))
}
pub fn random_ml_kem_768(mut csprng: impl CryptoRng) -> Self {
Self::MlKem768X25519(x25519_dalek::StaticSecret::random_from_rng(&mut csprng))
}
pub fn random_ml_kem_1024(mut csprng: impl CryptoRng) -> Self {
Self::MlKem1024X25519(x25519_dalek::StaticSecret::random_from_rng(&mut csprng))
}
pub fn public(&self) -> StaticPublicKey {
match self {
Self::X25519(key) => StaticPublicKey::X25519(x25519_dalek::PublicKey::from(key)),
Self::MlKem512X25519(key) =>
StaticPublicKey::MlKem512X25519(x25519_dalek::PublicKey::from(key)),
Self::MlKem768X25519(key) =>
StaticPublicKey::MlKem768X25519(x25519_dalek::PublicKey::from(key)),
Self::MlKem1024X25519(key) =>
StaticPublicKey::MlKem1024X25519(x25519_dalek::PublicKey::from(key)),
}
}
pub fn diffie_hellman<T: AsRef<x25519_dalek::PublicKey>>(&self, public_key: &T) -> Vec<u8> {
match self {
Self::X25519(key) => key.diffie_hellman(public_key.as_ref()).to_bytes().to_vec(),
Self::MlKem512X25519(key) =>
key.diffie_hellman(public_key.as_ref()).to_bytes().to_vec(),
Self::MlKem768X25519(key) =>
key.diffie_hellman(public_key.as_ref()).to_bytes().to_vec(),
Self::MlKem1024X25519(key) =>
key.diffie_hellman(public_key.as_ref()).to_bytes().to_vec(),
}
}
pub fn from_bytes(bytes: [u8; 32]) -> Self {
Self::X25519(x25519_dalek::StaticSecret::from(bytes))
}
pub fn from_bytes_ml_kem_512(bytes: [u8; 32]) -> Self {
Self::MlKem512X25519(x25519_dalek::StaticSecret::from(bytes))
}
pub fn from_bytes_ml_kem_768(bytes: [u8; 32]) -> Self {
Self::MlKem768X25519(x25519_dalek::StaticSecret::from(bytes))
}
pub fn from_bytes_ml_kem_1024(bytes: [u8; 32]) -> Self {
Self::MlKem1024X25519(x25519_dalek::StaticSecret::from(bytes))
}
pub fn try_from_bytes(bytes: &[u8]) -> Option<Self> {
let key: [u8; 32] = bytes.try_into().ok()?;
Some(Self::X25519(x25519_dalek::StaticSecret::from(key)))
}
pub fn try_from_bytes_ml_kem_512(bytes: &[u8]) -> Option<Self> {
let key: [u8; 32] = bytes.try_into().ok()?;
Some(Self::MlKem512X25519(x25519_dalek::StaticSecret::from(key)))
}
pub fn try_from_bytes_ml_kem_768(bytes: &[u8]) -> Option<Self> {
let key: [u8; 32] = bytes.try_into().ok()?;
Some(Self::MlKem768X25519(x25519_dalek::StaticSecret::from(key)))
}
pub fn try_from_bytes_ml_kem_1024(bytes: &[u8]) -> Option<Self> {
let key: [u8; 32] = bytes.try_into().ok()?;
Some(Self::MlKem1024X25519(x25519_dalek::StaticSecret::from(key)))
}
}
impl AsRef<[u8]> for StaticPrivateKey {
fn as_ref(&self) -> &[u8] {
match self {
Self::X25519(key) => key.as_ref(),
Self::MlKem512X25519(key) => key.as_ref(),
Self::MlKem768X25519(key) => key.as_ref(),
Self::MlKem1024X25519(key) => key.as_ref(),
}
}
}
impl SecretKey for StaticPrivateKey {
fn diffie_hellman<T: AsRef<x25519_dalek::PublicKey>>(&self, public_key: &T) -> [u8; 32] {
match self {
Self::X25519(key) => key.diffie_hellman(public_key.as_ref()).to_bytes(),
Self::MlKem512X25519(key) => key.diffie_hellman(public_key.as_ref()).to_bytes(),
Self::MlKem768X25519(key) => key.diffie_hellman(public_key.as_ref()).to_bytes(),
Self::MlKem1024X25519(key) => key.diffie_hellman(public_key.as_ref()).to_bytes(),
}
}
}
pub enum EphemeralPrivateKey {
X25519(x25519_dalek::ReusableSecret),
MlKem512X25519(x25519_dalek::ReusableSecret),
MlKem768X25519(x25519_dalek::ReusableSecret),
MlKem1024X25519(x25519_dalek::ReusableSecret),
}
impl EphemeralPrivateKey {
pub fn random(mut csprng: impl CryptoRng) -> Self {
Self::X25519(x25519_dalek::ReusableSecret::random_from_rng(&mut csprng))
}
pub fn random_ml_kem_512(mut csprng: impl CryptoRng) -> Self {
Self::MlKem512X25519(x25519_dalek::ReusableSecret::random_from_rng(&mut csprng))
}
pub fn random_ml_kem_768(mut csprng: impl CryptoRng) -> Self {
Self::MlKem768X25519(x25519_dalek::ReusableSecret::random_from_rng(&mut csprng))
}
pub fn random_ml_kem_1024(mut csprng: impl CryptoRng) -> Self {
Self::MlKem1024X25519(x25519_dalek::ReusableSecret::random_from_rng(&mut csprng))
}
pub fn public(&self) -> EphemeralPublicKey {
match self {
Self::X25519(key) => EphemeralPublicKey::X25519(x25519_dalek::PublicKey::from(key)),
Self::MlKem512X25519(key) =>
EphemeralPublicKey::MlKem512X25519(x25519_dalek::PublicKey::from(key)),
Self::MlKem768X25519(key) =>
EphemeralPublicKey::MlKem768X25519(x25519_dalek::PublicKey::from(key)),
Self::MlKem1024X25519(key) =>
EphemeralPublicKey::MlKem1024X25519(x25519_dalek::PublicKey::from(key)),
}
}
pub fn diffie_hellman<T: AsRef<x25519_dalek::PublicKey>>(&self, public_key: &T) -> Vec<u8> {
match self {
Self::X25519(key) => key.diffie_hellman(public_key.as_ref()).to_bytes().to_vec(),
Self::MlKem512X25519(key) =>
key.diffie_hellman(public_key.as_ref()).to_bytes().to_vec(),
Self::MlKem768X25519(key) =>
key.diffie_hellman(public_key.as_ref()).to_bytes().to_vec(),
Self::MlKem1024X25519(key) =>
key.diffie_hellman(public_key.as_ref()).to_bytes().to_vec(),
}
}
}
impl SecretKey for EphemeralPrivateKey {
fn diffie_hellman<T: AsRef<x25519_dalek::PublicKey>>(&self, public_key: &T) -> [u8; 32] {
match self {
Self::X25519(key) => key.diffie_hellman(public_key.as_ref()).to_bytes(),
Self::MlKem512X25519(key) => key.diffie_hellman(public_key.as_ref()).to_bytes(),
Self::MlKem768X25519(key) => key.diffie_hellman(public_key.as_ref()).to_bytes(),
Self::MlKem1024X25519(key) => key.diffie_hellman(public_key.as_ref()).to_bytes(),
}
}
}
#[derive(Clone)]
pub enum EphemeralPublicKey {
X25519(x25519_dalek::PublicKey),
MlKem512X25519(x25519_dalek::PublicKey),
MlKem768X25519(x25519_dalek::PublicKey),
MlKem1024X25519(x25519_dalek::PublicKey),
}
impl EphemeralPublicKey {
pub fn to_vec(&self) -> Vec<u8> {
match self {
Self::X25519(key) => key.as_bytes().to_vec(),
Self::MlKem512X25519(key) => key.as_bytes().to_vec(),
Self::MlKem768X25519(key) => key.as_bytes().to_vec(),
Self::MlKem1024X25519(key) => key.as_bytes().to_vec(),
}
}
pub fn try_from_bytes(bytes: &[u8]) -> Option<Self> {
let key: [u8; 32] = bytes.try_into().ok()?;
Some(Self::X25519(x25519_dalek::PublicKey::from(key)))
}
pub fn try_from_bytes_ml_kem_512(bytes: &[u8]) -> Option<Self> {
let key: [u8; 32] = bytes.try_into().ok()?;
Some(Self::MlKem512X25519(x25519_dalek::PublicKey::from(key)))
}
pub fn try_from_bytes_ml_kem_768(bytes: &[u8]) -> Option<Self> {
let key: [u8; 32] = bytes.try_into().ok()?;
Some(Self::MlKem768X25519(x25519_dalek::PublicKey::from(key)))
}
pub fn try_from_bytes_ml_kem_1024(bytes: &[u8]) -> Option<Self> {
let key: [u8; 32] = bytes.try_into().ok()?;
Some(Self::MlKem1024X25519(x25519_dalek::PublicKey::from(key)))
}
}
impl AsRef<[u8]> for EphemeralPublicKey {
fn as_ref(&self) -> &[u8] {
match self {
Self::X25519(key) => key.as_ref(),
Self::MlKem512X25519(key) => key.as_ref(),
Self::MlKem768X25519(key) => key.as_ref(),
Self::MlKem1024X25519(key) => key.as_ref(),
}
}
}
impl AsRef<x25519_dalek::PublicKey> for EphemeralPublicKey {
fn as_ref(&self) -> &x25519_dalek::PublicKey {
match self {
Self::X25519(key) => key,
Self::MlKem512X25519(key) => key,
Self::MlKem768X25519(key) => key,
Self::MlKem1024X25519(key) => key,
}
}
}
impl Zeroize for EphemeralPublicKey {
fn zeroize(&mut self) {
match self {
Self::X25519(key) => key.zeroize(),
Self::MlKem512X25519(key) => key.zeroize(),
Self::MlKem768X25519(key) => key.zeroize(),
Self::MlKem1024X25519(key) => key.zeroize(),
}
}
}
#[derive(Clone)]
pub enum SigningPrivateKey {
Ed25519(ed25519_dalek::SigningKey),
}
impl SigningPrivateKey {
pub fn random(mut csprng: impl CryptoRng) -> Self {
Self::Ed25519(ed25519_dalek::SigningKey::generate(&mut csprng))
}
pub fn from_bytes(key: &[u8]) -> Option<Self> {
let key: [u8; 32] = key.to_vec().try_into().ok()?;
let key = ed25519_dalek::SigningKey::from_bytes(&key);
Some(SigningPrivateKey::Ed25519(key))
}
pub fn sign(&self, message: &[u8]) -> Vec<u8> {
match self {
Self::Ed25519(key) => key.sign(message).to_bytes().to_vec(),
}
}
pub fn public(&self) -> SigningPublicKey {
match self {
Self::Ed25519(key) => SigningPublicKey::Ed25519(key.verifying_key()),
}
}
pub fn signature_len(&self) -> usize {
match self {
Self::Ed25519(_) => 64usize,
}
}
}
impl From<[u8; 32]> for SigningPrivateKey {
fn from(value: [u8; 32]) -> Self {
SigningPrivateKey::Ed25519(ed25519_dalek::SigningKey::from(value))
}
}
impl AsRef<[u8]> for SigningPrivateKey {
fn as_ref(&self) -> &[u8] {
match self {
Self::Ed25519(key) => key.as_bytes(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SigningPublicKey {
Ed25519(ed25519_dalek::VerifyingKey),
P256(p256::EncodedPoint, p256::ecdsa::VerifyingKey),
DsaSha1(DsaPublicKey),
}
impl SigningPublicKey {
pub fn from_bytes(key: &[u8; 32]) -> Option<Self> {
Some(SigningPublicKey::Ed25519(
ed25519_dalek::VerifyingKey::from_bytes(key).ok()?,
))
}
pub fn p256(data: &[u8]) -> Option<Self> {
let encoded = p256::EncodedPoint::from_untagged_bytes(data.into());
Some(Self::P256(
encoded,
p256::ecdsa::VerifyingKey::from_encoded_point(&encoded).ok()?,
))
}
pub fn dsa_sha1(data: &[u8]) -> Option<Self> {
DsaPublicKey::from_bytes(data).map(Self::DsaSha1)
}
pub fn verify(&self, message: &[u8], signature: &[u8]) -> crate::Result<()> {
match self {
Self::Ed25519(key) => {
let signature: [u8; 64] = signature.try_into().map_err(|_| Error::InvalidData)?;
let signature = ed25519_dalek::Signature::from_bytes(&signature);
key.verify_strict(message, &signature).map_err(From::from)
}
Self::P256(_, vk) => {
let signature =
p256::ecdsa::Signature::try_from(signature).map_err(|_| Error::InvalidData)?;
vk.verify(message, &signature).map_err(|_| Error::InvalidData)
}
Self::DsaSha1(public_key) => {
let signature = DsaSignature::from_bytes(signature).ok_or(Error::InvalidData)?;
match public_key.verify(message, &signature) {
true => Ok(()),
false => Err(Error::InvalidData),
}
}
}
}
pub fn signature_len(&self) -> usize {
match self {
Self::Ed25519(_) => 64usize,
Self::P256(_, _) => 64usize,
Self::DsaSha1(_) => 40usize,
}
}
}
impl AsRef<[u8]> for SigningPublicKey {
fn as_ref(&self) -> &[u8] {
match self {
Self::Ed25519(key) => key.as_bytes(),
Self::P256(pk, _) => &pk.as_bytes()[1..],
Self::DsaSha1(key) => key.as_bytes(),
}
}
}