use num_bigint_dig::BigUint;
use rand::rngs::OsRng;
use rsa::{PublicKeyParts, RSAPrivateKey, RSAPublicKey};
use std::fmt;
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct BigNum {
value: Vec<u8>,
}
impl BigNum {
pub fn to_string_unstable(&self) -> String {
unsafe { String::from_utf8_unchecked(self.value.clone()) }
}
}
impl From<&BigUint> for BigNum {
fn from(num: &BigUint) -> Self {
Self {
value: num.to_bytes_be(),
}
}
}
impl From<&BigNum> for BigUint {
fn from(num: &BigNum) -> Self {
BigUint::from_bytes_be(&num.value)
}
}
impl PartialEq<BigUint> for BigNum {
fn eq(&self, other: &BigUint) -> bool {
self.value == other.to_bytes_be()
}
}
impl PartialEq<BigNum> for BigUint {
fn eq(&self, other: &BigNum) -> bool {
self.to_bytes_be() == other.value
}
}
impl fmt::Display for BigNum {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.value)
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct PubKeyComp {
n: BigNum,
e: BigNum,
}
impl PubKeyComp {
pub fn from_parts(n: BigNum, e: BigNum) -> Self {
Self { n, e }
}
pub fn n(&self) -> &BigNum {
&self.n
}
pub fn e(&self) -> &BigNum {
&self.e
}
}
impl PartialEq<RSAPublicKey> for PubKeyComp {
fn eq(&self, pubkey: &RSAPublicKey) -> bool {
self.n == *pubkey.n() && self.e == *pubkey.e()
}
}
impl PartialEq<PubKeyComp> for RSAPublicKey {
fn eq(&self, pubkey: &PubKeyComp) -> bool {
*self.n() == pubkey.n && *self.e() == pubkey.e
}
}
impl From<&RSAPublicKey> for PubKeyComp {
fn from(public_key: &RSAPublicKey) -> Self {
Self::from_parts(BigNum::from(public_key.n()), BigNum::from(public_key.e()))
}
}
impl From<&RSAPrivateKey> for PubKeyComp {
fn from(private_key: &RSAPrivateKey) -> Self {
Self::from(&RSAPublicKey::from(private_key))
}
}
impl From<&PrivKeyComp> for PubKeyComp {
fn from(priv_key: &PrivKeyComp) -> Self {
Self {
n: priv_key.n().to_owned(),
e: priv_key.e().to_owned(),
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct PrivKeyComp {
n: BigNum,
e: BigNum,
d: BigNum,
primes: Vec<BigNum>,
}
impl PrivKeyComp {
pub fn n(&self) -> &BigNum {
&self.n
}
pub fn e(&self) -> &BigNum {
&self.e
}
pub fn d(&self) -> &BigNum {
&self.d
}
pub fn primes(&self) -> &Vec<BigNum> {
&self.primes
}
pub fn into_components(self) -> (BigNum, BigNum, BigNum, Vec<BigNum>) {
(self.n, self.e, self.d, self.primes)
}
pub fn generate() -> rsa::errors::Result<Self> {
let mut rng = OsRng;
let bits = 2048;
let private_key = RSAPrivateKey::new(&mut rng, bits)?;
let d = BigNum::from(private_key.d());
let primes: Vec<BigNum> = private_key
.primes()
.iter()
.map(|p| BigNum::from(p))
.collect();
let n = BigNum::from(private_key.n());
let e = BigNum::from(private_key.e());
Ok(Self { n, e, d, primes })
}
}
impl From<&RSAPrivateKey> for PrivKeyComp {
fn from(key: &RSAPrivateKey) -> Self {
let primes = key.primes().iter().map(|p| BigNum::from(p)).collect();
let d = BigNum::from(key.d());
let public_key = RSAPublicKey::from(key);
let n = BigNum::from(public_key.n());
let e = BigNum::from(public_key.e());
Self { n, e, d, primes }
}
}
impl From<&PrivKeyComp> for RSAPrivateKey {
fn from(comp: &PrivKeyComp) -> RSAPrivateKey {
RSAPrivateKey::from_components(
comp.n().into(),
comp.e().into(),
comp.d().into(),
comp.primes.iter().map(|p| BigUint::from(p)).collect(),
)
}
}