citadel-tools/libcitadel/src/keys.rs

104 lines
2.8 KiB
Rust
Raw Normal View History

use Result;
2018-12-31 18:27:17 -05:00
use ring::rand;
use ring::signature::{self,Ed25519KeyPair,ED25519_PUBLIC_KEY_LEN,ED25519_PKCS8_V2_LEN};
use untrusted::Input;
use rustc_serialize::hex::{FromHex,ToHex};
///
/// Keys for signing or verifying signatures. Small convenience
2018-12-31 18:27:17 -05:00
/// wrapper around `ring/ed25519`.
///
///
2018-12-31 18:27:17 -05:00
pub struct PublicKey([u8; ED25519_PUBLIC_KEY_LEN]);
pub struct KeyPair([u8; ED25519_PKCS8_V2_LEN]);
pub struct Signature(signature::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> {
let bytes = hex.from_hex()?;
if bytes.len() != ED25519_PUBLIC_KEY_LEN {
bail!("Hex encoded public key has invalid length: {}", bytes.len());
}
Ok(PublicKey::from_bytes(&bytes))
}
pub fn to_hex(&self) -> String {
self.0.to_hex()
}
fn from_bytes(bytes: &[u8]) -> PublicKey {
2018-12-31 18:27:17 -05:00
let mut key = [0u8; ED25519_PUBLIC_KEY_LEN];
key.copy_from_slice(bytes);
2019-01-05 20:38:57 -05:00
PublicKey(key)
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 {
2018-12-31 18:27:17 -05:00
let signature = Input::from(signature);
let data = Input::from(data);
let pubkey = Input::from(&self.0);
2019-01-05 20:38:57 -05:00
match signature::verify(&signature::ED25519, pubkey, data, signature) {
Ok(()) => true,
Err(_) => false,
}
2018-12-31 18:27:17 -05:00
}
}
2018-12-31 18:27:17 -05:00
impl KeyPair {
/// Generate a new pair of signing/verifying keys using
/// the system random number generator. The resulting
2018-12-31 18:27:17 -05:00
/// `Ed25519KeyPair` can be extracted in an ascii
/// hex encoded pkcs#8 format for storage in configuration files
/// with the `to_hex()` method.
2018-12-31 18:27:17 -05:00
pub fn generate() -> Result<KeyPair> {
let rng = rand::SystemRandom::new();
let bytes = Ed25519KeyPair::generate_pkcs8(&rng)?;
KeyPair::from_bytes(&bytes)
}
2018-12-31 18:27:17 -05:00
pub fn from_hex(hex: &str) -> Result<KeyPair> {
KeyPair::from_bytes(&hex.from_hex()?)
}
2018-12-31 18:27:17 -05:00
fn from_bytes(bytes: &[u8]) -> Result<KeyPair> {
let mut pair = [0u8; ED25519_PKCS8_V2_LEN];
pair.copy_from_slice(bytes);
2019-01-05 20:38:57 -05:00
let _ = Ed25519KeyPair::from_pkcs8(Input::from(&pair))?;
2018-12-31 18:27:17 -05:00
Ok(KeyPair(pair))
}
2019-01-05 20:38:57 -05:00
fn get_keys(&self) -> Ed25519KeyPair {
Ed25519KeyPair::from_pkcs8(Input::from(&self.0))
.expect("failed to parse pkcs8 key")
}
2019-01-05 20:38:57 -05:00
pub fn public_key(&self) -> PublicKey {
let keys = self.get_keys();
PublicKey::from_bytes(keys.public_key_bytes())
}
2018-12-31 18:27:17 -05:00
pub fn private_key_hex(&self) -> String {
self.0.to_hex()
}
2019-01-05 20:38:57 -05:00
pub fn sign(&self, data: &[u8]) -> Signature {
let keys = self.get_keys();
let signature = keys.sign(data);
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] {
self.0.as_ref()
}
}
2018-12-31 18:27:17 -05:00