citadel-tools/libcitadel/src/keys.rs

86 lines
2.3 KiB
Rust
Raw Normal View History

use crate::Result;
2019-02-02 20:33:50 -05:00
use sodiumoxide::randombytes::randombytes_into;
use sodiumoxide::crypto::sign::{self,Seed,SEEDBYTES,PUBLICKEYBYTES};
use hex;
///
/// Keys for signing or verifying signatures. Small convenience
2019-02-02 20:33:50 -05:00
/// wrapper around `sodiumoxide::crypto::sign`.
2018-12-31 18:27:17 -05:00
///
///
#[derive(Clone)]
2019-02-02 20:33:50 -05:00
pub struct PublicKey(sign::PublicKey);
pub struct KeyPair(Seed);
pub struct Signature(sign::Signature);
2018-12-31 18:27:17 -05:00
impl PublicKey {
2019-01-05 20:38:57 -05:00
pub fn from_hex(hex: &str) -> Result<PublicKey> {
2019-02-02 20:33:50 -05:00
let bytes = hex::decode(hex)?;
if bytes.len() != PUBLICKEYBYTES {
2019-01-05 20:38:57 -05:00
bail!("Hex encoded public key has invalid length: {}", bytes.len());
}
2019-02-02 20:33:50 -05:00
let pubkey = sign::PublicKey::from_slice(&bytes)
.expect("PublicKey::from_slice() failed");
Ok(PublicKey(pubkey))
2019-01-05 20:38:57 -05:00
}
pub fn to_hex(&self) -> String {
2019-02-02 20:33:50 -05:00
hex::encode(&(self.0).0)
2018-12-31 18:27:17 -05:00
}
2019-01-05 20:38:57 -05:00
pub fn verify(&self, data: &[u8], signature: &[u8]) -> bool {
2019-02-02 20:33:50 -05:00
let sig = sign::Signature::from_slice(signature)
.expect("Signature::from_slice() failed");
sign::verify_detached(&sig, data, &self.0)
2018-12-31 18:27:17 -05:00
}
}
2018-12-31 18:27:17 -05:00
impl KeyPair {
2019-02-02 20:33:50 -05:00
/// Create a new pair of signing/verifying keys by generating a random seed
/// The secret and public keys can be derived from the seed.
pub fn generate() -> KeyPair {
let mut seedbuf = [0; SEEDBYTES];
randombytes_into(&mut seedbuf);
KeyPair(sign::Seed(seedbuf))
}
2018-12-31 18:27:17 -05:00
pub fn from_hex(hex: &str) -> Result<KeyPair> {
2019-02-02 20:33:50 -05:00
let bytes = hex::decode(hex)?;
if bytes.len() != SEEDBYTES {
bail!("Hex encoded keypair has incorrect length");
}
let seed = sign::Seed::from_slice(&bytes).expect("Seed::from_slice() failed");
Ok(KeyPair(seed))
}
2019-01-05 20:38:57 -05:00
pub fn public_key(&self) -> PublicKey {
2019-02-02 20:33:50 -05:00
let (pk,_) = sign::keypair_from_seed(&self.0);
PublicKey(pk)
}
2019-02-02 20:33:50 -05:00
pub fn to_hex(&self) -> String {
hex::encode(&(self.0).0)
2018-12-31 18:27:17 -05:00
}
2019-01-05 20:38:57 -05:00
pub fn sign(&self, data: &[u8]) -> Signature {
2019-02-02 20:33:50 -05:00
let (_,sk) = sign::keypair_from_seed(&self.0);
let signature = sign::sign_detached(data, &sk);
2019-01-05 20:38:57 -05:00
Signature(signature)
}
2019-01-05 20:38:57 -05:00
pub fn verify(&self, data: &[u8], signature: &[u8]) -> bool {
self.public_key().verify(data, signature)
}
2018-12-31 18:27:17 -05:00
}
2018-12-31 18:27:17 -05:00
impl Signature {
pub fn to_bytes(&self) -> &[u8] {
2019-02-02 20:33:50 -05:00
&(self.0).0
}
}
2018-12-31 18:27:17 -05:00