use crate::ffi;
use crate::error::{check, Error};
use crate::types::{NodeId, Identity};
pub struct Keypair {
inner: Box<ffi::nwep_keypair>,
}
impl Keypair {
pub fn generate() -> Result<Self, Error> {
let mut kp = Box::new(ffi::nwep_keypair { pubkey: [0u8; 32], privkey: [0u8; 64] });
check(unsafe { ffi::nwep_keypair_generate(kp.as_mut()) })?;
Ok(Keypair { inner: kp })
}
pub fn from_seed(seed: &[u8; 32]) -> Result<Self, Error> {
let mut kp = Box::new(ffi::nwep_keypair { pubkey: [0u8; 32], privkey: [0u8; 64] });
check(unsafe { ffi::nwep_keypair_from_seed(kp.as_mut(), seed.as_ptr()) })?;
Ok(Keypair { inner: kp })
}
pub fn from_privkey(privkey: &[u8; 64]) -> Result<Self, Error> {
let mut kp = Box::new(ffi::nwep_keypair { pubkey: [0u8; 32], privkey: [0u8; 64] });
check(unsafe { ffi::nwep_keypair_from_privkey(kp.as_mut(), privkey.as_ptr()) })?;
Ok(Keypair { inner: kp })
}
pub fn public_key(&self) -> [u8; 32] {
self.inner.pubkey
}
pub fn seed(&self) -> [u8; 32] {
let mut seed = [0u8; 32];
seed.copy_from_slice(&self.inner.privkey[..32]);
seed
}
pub fn private_key(&self) -> [u8; 64] {
self.inner.privkey
}
pub fn node_id(&self) -> Result<NodeId, Error> {
let mut nid = ffi::nwep_nodeid { data: [0u8; 32] };
check(unsafe { ffi::nwep_nodeid_from_keypair(&mut nid, self.inner.as_ref()) })?;
Ok(NodeId(nid.data))
}
pub fn clear(&mut self) {
unsafe { ffi::nwep_keypair_clear(self.inner.as_mut()) }
}
pub(crate) fn as_ffi(&self) -> &ffi::nwep_keypair {
self.inner.as_ref()
}
pub(crate) fn as_ffi_mut(&mut self) -> &mut ffi::nwep_keypair {
self.inner.as_mut()
}
}
unsafe impl Send for Keypair {}
impl Drop for Keypair {
fn drop(&mut self) {
self.clear();
}
}
pub fn node_id_from_pubkey(pubkey: &[u8; 32]) -> Result<NodeId, Error> {
let mut nid = ffi::nwep_nodeid { data: [0u8; 32] };
check(unsafe { ffi::nwep_nodeid_from_pubkey(&mut nid, pubkey.as_ptr()) })?;
Ok(NodeId(nid.data))
}
pub fn node_id_eq(a: &NodeId, b: &NodeId) -> bool {
let fa = ffi::nwep_nodeid { data: a.0 };
let fb = ffi::nwep_nodeid { data: b.0 };
unsafe { ffi::nwep_nodeid_eq(&fa, &fb) != 0 }
}
pub struct RecoveryAuthority {
inner: ffi::nwep_recovery_authority,
}
impl RecoveryAuthority {
pub fn new() -> Result<Self, Error> {
let mut ra = ffi::nwep_recovery_authority {
keypair: ffi::nwep_keypair { pubkey: [0u8; 32], privkey: [0u8; 64] },
initialized: 0,
};
check(unsafe { ffi::nwep_recovery_authority_new(&mut ra) })?;
Ok(RecoveryAuthority { inner: ra })
}
pub fn from_keypair(kp: &Keypair) -> Result<Self, Error> {
let mut ra = ffi::nwep_recovery_authority {
keypair: ffi::nwep_keypair { pubkey: [0u8; 32], privkey: [0u8; 64] },
initialized: 0,
};
check(unsafe { ffi::nwep_recovery_authority_from_keypair(&mut ra, kp.as_ffi()) })?;
Ok(RecoveryAuthority { inner: ra })
}
pub fn public_key(&self) -> Option<[u8; 32]> {
let ptr = unsafe { ffi::nwep_recovery_authority_get_pubkey(&self.inner) };
if ptr.is_null() {
None
} else {
let mut pk = [0u8; 32];
unsafe { pk.copy_from_slice(std::slice::from_raw_parts(ptr, 32)) };
Some(pk)
}
}
pub fn clear(&mut self) {
unsafe { ffi::nwep_recovery_authority_clear(&mut self.inner) }
}
pub(crate) fn as_ffi(&self) -> &ffi::nwep_recovery_authority {
&self.inner
}
}
impl Drop for RecoveryAuthority {
fn drop(&mut self) {
self.clear();
}
}
pub struct ManagedIdentity {
inner: ffi::nwep_managed_identity,
}
impl ManagedIdentity {
pub fn new(kp: &Keypair, ra: Option<&RecoveryAuthority>, now: crate::Tstamp) -> Result<Self, Error> {
let mut mi = unsafe { std::mem::zeroed::<ffi::nwep_managed_identity>() };
let ra_ptr = ra.map_or(std::ptr::null(), |r| r.as_ffi());
check(unsafe { ffi::nwep_managed_identity_new(&mut mi, kp.as_ffi(), ra_ptr, now) })?;
Ok(ManagedIdentity { inner: mi })
}
pub fn rotate(&mut self, now: crate::Tstamp) -> Result<(), Error> {
check(unsafe { ffi::nwep_managed_identity_rotate(&mut self.inner, now) })
}
pub fn update(&mut self, now: crate::Tstamp) {
unsafe { ffi::nwep_managed_identity_update(&mut self.inner, now) }
}
pub fn is_revoked(&self) -> bool {
unsafe { ffi::nwep_managed_identity_is_revoked(&self.inner) != 0 }
}
pub fn revoke(&mut self, ra: &RecoveryAuthority, now: crate::Tstamp) -> Result<(), Error> {
check(unsafe { ffi::nwep_managed_identity_revoke(&mut self.inner, ra.as_ffi(), now) })
}
pub fn node_id(&self) -> NodeId {
NodeId(self.inner.nodeid.data)
}
pub fn active_keypair(&self) -> Option<Keypair> {
let ptr = unsafe { ffi::nwep_managed_identity_get_active(&self.inner) };
if ptr.is_null() {
None
} else {
Some(Keypair { inner: unsafe { Box::new(*ptr) } })
}
}
pub fn active_keys(&self) -> Vec<Keypair> {
let mut ptrs = [std::ptr::null::<ffi::nwep_keypair>(); crate::types::MAX_ACTIVE_KEYS];
let n = unsafe {
ffi::nwep_managed_identity_get_active_keys(
&self.inner,
ptrs.as_mut_ptr() as *mut *const ffi::nwep_keypair,
crate::types::MAX_ACTIVE_KEYS,
)
};
(0..n).filter_map(|i| {
if ptrs[i].is_null() { None } else { Some(Keypair { inner: unsafe { Box::new(*ptrs[i]) } }) }
}).collect()
}
pub fn active_pubkey(&self) -> Option<[u8; 32]> {
let ptr = unsafe { ffi::nwep_managed_identity_get_active(&self.inner) };
if ptr.is_null() {
None
} else {
Some(unsafe { (*ptr).pubkey })
}
}
pub fn identity(&self) -> Identity {
let pk = self.active_pubkey().unwrap_or([0u8; 32]);
Identity { pubkey: pk, node_id: self.node_id() }
}
pub fn clear(&mut self) {
unsafe { ffi::nwep_managed_identity_clear(&mut self.inner) }
}
#[allow(dead_code)]
pub(crate) fn as_ffi(&self) -> &ffi::nwep_managed_identity {
&self.inner
}
}
impl Drop for ManagedIdentity {
fn drop(&mut self) {
self.clear();
}
}
pub fn verify_revocation(rev: &Revocation) -> Result<(), Error> {
let ffi_rev = rev.to_ffi();
check(unsafe { ffi::nwep_managed_identity_verify_revocation(&ffi_rev) })
}
#[derive(Clone, Debug)]
pub struct Revocation {
pub node_id: NodeId,
pub timestamp: crate::Tstamp,
pub recovery_pubkey: [u8; 32],
pub signature: [u8; 64],
}
impl Revocation {
fn to_ffi(&self) -> ffi::nwep_revocation {
ffi::nwep_revocation {
nodeid: ffi::nwep_nodeid { data: self.node_id.0 },
timestamp: self.timestamp,
recovery_pubkey: self.recovery_pubkey,
signature: self.signature,
}
}
}