use std::{
fmt,
ops::{Index, Range, RangeFrom, RangeFull, RangeTo},
};
use super::sodiumoxide::crypto::{
scalarmult::curve25519::{
scalarmult as sodium_scalarmult, scalarmult_base as sodium_scalarmult_base,
GroupElement as Curve25519GroupElement, Scalar as Curve25519Scalar,
},
sign::ed25519::{
convert_ed_keypair_to_curve25519, convert_ed_pk_to_curve25519, convert_ed_sk_to_curve25519,
PublicKey as PublicKeySodium, SecretKey as SecretKeySodium,
},
};
use crate::{write_short_hex, PublicKey as crypto_PublicKey, SecretKey as crypto_SecretKey};
pub const PUBLIC_KEY_LENGTH: usize = 32;
pub const SECRET_KEY_LENGTH: usize = 32;
#[allow(clippy::needless_pass_by_value)]
pub fn into_x25519_keypair(
pk: crypto_PublicKey,
sk: crypto_SecretKey,
) -> Option<(PublicKey, SecretKey)> {
let pk_sod = PublicKeySodium::from_slice(&pk[..])?;
let sk_sod = SecretKeySodium::from_slice(&sk[..])?;
let (pk, sk) = convert_ed_keypair_to_curve25519(pk_sod, sk_sod);
let mut secret_key = [0; SECRET_KEY_LENGTH];
secret_key.clone_from_slice(&sk.0[..SECRET_KEY_LENGTH]);
Some((PublicKey::new(pk.0), SecretKey::new(secret_key)))
}
pub fn convert_to_private_key(key: &mut [u8; 32]) {
let converted = convert_ed_sk_to_curve25519(key);
key.copy_from_slice(&converted);
}
pub fn scalarmult(sc: &SecretKey, pk: &PublicKey) -> Result<PublicKey, ()> {
sodium_scalarmult(sc.as_ref(), pk.as_ref()).map(PublicKey)
}
pub fn scalarmult_base(sc: &SecretKey) -> PublicKey {
sodium_scalarmult_base(sc.as_ref()).into()
}
pub fn into_x25519_public_key(pk: crypto_PublicKey) -> PublicKey {
let mut public_key = [0; PUBLIC_KEY_LENGTH];
public_key.clone_from_slice(&pk[..PUBLIC_KEY_LENGTH]);
let public_key = convert_ed_pk_to_curve25519(&public_key);
PublicKey(Curve25519GroupElement(public_key))
}
macro_rules! implement_x25519_type {
($(#[$attr:meta])* struct $name:ident, $name_from:ident, $size:expr) => (
#[derive(PartialEq, Eq, Clone)]
$(#[$attr])*
pub struct $name($name_from);
impl $name {
pub fn zero() -> Self {
$name::new([0; $size])
}
}
impl $name {
pub fn new(bytes_array: [u8; $size]) -> Self {
$name($name_from(bytes_array))
}
pub fn from_slice(bytes_slice: &[u8]) -> Option<Self> {
$name_from::from_slice(bytes_slice).map($name)
}
}
impl AsRef<[u8]> for $name {
fn as_ref(&self) -> &[u8] {
&self.0[..]
}
}
impl AsRef<$name_from> for $name {
fn as_ref(&self) -> &$name_from {
&self.0
}
}
impl fmt::Debug for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, stringify!($name))?;
write!(f, "(")?;
write_short_hex(f, &self.0[..])?;
write!(f, ")")
}
}
impl Into<$name> for $name_from {
fn into(self) -> $name {
$name(self)
}
}
)
}
implement_x25519_type! {
struct PublicKey, Curve25519GroupElement, PUBLIC_KEY_LENGTH
}
implement_x25519_type! {
struct SecretKey, Curve25519Scalar, SECRET_KEY_LENGTH
}
implement_index_traits! { PublicKey }
implement_index_traits! { SecretKey }