cert signing tests
This commit is contained in:
parent
020abccf79
commit
33ba674073
|
@ -555,6 +555,7 @@ checksum = "7bd577ba9d4bcab443cac60003d8fd32c638e7024a3ec92c200d7af5d2c397ed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"curve25519-dalek 4.0.0-rc.1",
|
"curve25519-dalek 4.0.0-rc.1",
|
||||||
"ed25519",
|
"ed25519",
|
||||||
|
"rand_core 0.6.4",
|
||||||
"serde",
|
"serde",
|
||||||
"sha2",
|
"sha2",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
|
@ -2425,6 +2426,8 @@ dependencies = [
|
||||||
"ipnet",
|
"ipnet",
|
||||||
"pem",
|
"pem",
|
||||||
"quick-protobuf",
|
"quick-protobuf",
|
||||||
|
"rand",
|
||||||
|
"rand_core 0.6.4",
|
||||||
"sha2",
|
"sha2",
|
||||||
"x25519-dalek",
|
"x25519-dalek",
|
||||||
]
|
]
|
||||||
|
|
|
@ -9,8 +9,10 @@ description = "A rust implementation of the Nebula PKI system"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
pem = "1.1.1"
|
pem = "1.1.1"
|
||||||
x25519-dalek = "2.0.0-pre.1"
|
x25519-dalek = "2.0.0-pre.1"
|
||||||
ed25519-dalek = "2.0.0-pre.0"
|
ed25519-dalek = { version = "2.0.0-pre.0", features = ["rand_core", "alloc"] }
|
||||||
ipnet = "2.7.1"
|
ipnet = "2.7.1"
|
||||||
quick-protobuf = "0.8.1"
|
quick-protobuf = "0.8.1"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
sha2 = "0.10.6"
|
sha2 = "0.10.6"
|
||||||
|
rand_core = "0.6.4"
|
||||||
|
rand = "0.8.5"
|
|
@ -3,6 +3,7 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::time::SystemTime;
|
||||||
use ed25519_dalek::VerifyingKey;
|
use ed25519_dalek::VerifyingKey;
|
||||||
use crate::cert::{deserialize_nebula_certificate_from_pem, NebulaCertificate};
|
use crate::cert::{deserialize_nebula_certificate_from_pem, NebulaCertificate};
|
||||||
|
|
||||||
|
@ -55,10 +56,25 @@ impl NebulaCAPool {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !cert.check_signature(&VerifyingKey::from_bytes(&cert.details.public_key)?)? {
|
if !cert.check_signature(&VerifyingKey::from_bytes(&cert.details.public_key)?)? {
|
||||||
|
return Err(CaPoolError::NotSelfSigned.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(false)
|
let fingerprint = cert.sha256sum()?;
|
||||||
|
let expired = cert.expired(SystemTime::now());
|
||||||
|
|
||||||
|
self.cas.insert(fingerprint, cert);
|
||||||
|
|
||||||
|
Ok(expired)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Blocklist the given certificate in the CA pool
|
||||||
|
pub fn blocklist_fingerprint(&mut self, fingerprint: &str) {
|
||||||
|
self.cert_blocklist.push(fingerprint.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clears the list of blocklisted fingerprints
|
||||||
|
pub fn reset_blocklist(&mut self) {
|
||||||
|
self.cert_blocklist = vec![];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the given certificate is blocklisted
|
/// Checks if the given certificate is blocklisted
|
||||||
|
@ -77,6 +93,11 @@ impl NebulaCAPool {
|
||||||
|
|
||||||
Ok(self.cas.get(&cert.details.issuer))
|
Ok(self.cas.get(&cert.details.issuer))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a list of trusted CA fingerprints
|
||||||
|
pub fn get_fingerprints(&self) -> Vec<&String> {
|
||||||
|
self.cas.keys().collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -7,7 +7,6 @@ use std::net::Ipv4Addr;
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
|
use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
|
||||||
use ed25519_dalek::ed25519::pkcs8::spki::der::Encode;
|
|
||||||
use ipnet::{Ipv4Net};
|
use ipnet::{Ipv4Net};
|
||||||
use pem::Pem;
|
use pem::Pem;
|
||||||
use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer};
|
use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer};
|
||||||
|
@ -294,14 +293,9 @@ impl NebulaCertificate {
|
||||||
pub fn sign(&mut self, key: &SigningKey) -> Result<(), Box<dyn Error>> {
|
pub fn sign(&mut self, key: &SigningKey) -> Result<(), Box<dyn Error>> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
let mut writer = Writer::new(&mut out);
|
let mut writer = Writer::new(&mut out);
|
||||||
writer.write_message(&self.get_raw_details())?;
|
self.get_raw_details().write_message(&mut writer)?;
|
||||||
|
|
||||||
let sig = key.sign(&out).to_bytes();
|
self.signature = key.sign(&out).to_vec();
|
||||||
|
|
||||||
self.signature = match sig.to_vec() {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(_) => return Err("signature error".into())
|
|
||||||
};
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,9 +305,11 @@ impl NebulaCertificate {
|
||||||
pub fn check_signature(&self, key: &VerifyingKey) -> Result<bool, Box<dyn Error>> {
|
pub fn check_signature(&self, key: &VerifyingKey) -> Result<bool, Box<dyn Error>> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
let mut writer = Writer::new(&mut out);
|
let mut writer = Writer::new(&mut out);
|
||||||
writer.write_message(&self.get_raw_details())?;
|
self.get_raw_details().write_message(&mut writer)?;
|
||||||
|
|
||||||
Ok(key.verify(&out, &Signature::try_from(&*self.signature)?).is_ok())
|
let sig = Signature::from_slice(&self.signature)?;
|
||||||
|
|
||||||
|
Ok(key.verify(&out, &sig).is_ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the signature is too young or too old compared to the provided time
|
/// Returns true if the signature is too young or too old compared to the provided time
|
||||||
|
|
|
@ -8,6 +8,8 @@ use std::time::{Duration, SystemTime, SystemTimeError, UNIX_EPOCH};
|
||||||
use ipnet::Ipv4Net;
|
use ipnet::Ipv4Net;
|
||||||
use crate::cert::{deserialize_nebula_certificate, NebulaCertificate, NebulaCertificateDetails};
|
use crate::cert::{deserialize_nebula_certificate, NebulaCertificate, NebulaCertificateDetails};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use ed25519_dalek::{SigningKey};
|
||||||
|
use rand::rngs::OsRng;
|
||||||
|
|
||||||
/// This is a cert that we (e3team) actually use in production, and it's a known-good certificate.
|
/// This is a cert that we (e3team) actually use in production, and it's a known-good certificate.
|
||||||
pub const KNOWN_GOOD_CERT: &[u8; 258] = b"-----BEGIN NEBULA CERTIFICATE-----\nCkkKF2UzdGVhbSBJbnRlcm5hbCBOZXR3b3JrKJWev5wGMJWFxKsGOiCvpwoHyKY5\n8Q5+2XxDjtoCf/zlNY/EUdB8bwXQSwEo50ABEkB0Dx76lkMqc3IyH5+ml2dKjTyv\nB4Jiw6x3abf5YZcf8rDuVEgQpvFdJmo3xJyIb3C9vKZ6kXsUxjw6s1JdWgkA\n-----END NEBULA CERTIFICATE-----";
|
pub const KNOWN_GOOD_CERT: &[u8; 258] = b"-----BEGIN NEBULA CERTIFICATE-----\nCkkKF2UzdGVhbSBJbnRlcm5hbCBOZXR3b3JrKJWev5wGMJWFxKsGOiCvpwoHyKY5\n8Q5+2XxDjtoCf/zlNY/EUdB8bwXQSwEo50ABEkB0Dx76lkMqc3IyH5+ml2dKjTyv\nB4Jiw6x3abf5YZcf8rDuVEgQpvFdJmo3xJyIb3C9vKZ6kXsUxjw6s1JdWgkA\n-----END NEBULA CERTIFICATE-----";
|
||||||
|
@ -68,6 +70,43 @@ fn certificate_serialization() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cert_signing() {
|
||||||
|
let before = round_systime_to_secs(SystemTime::now() - Duration::from_secs(60)).unwrap();
|
||||||
|
let after = round_systime_to_secs(SystemTime::now() + Duration::from_secs(60)).unwrap();
|
||||||
|
let pub_key = b"1234567890abcedfghij1234567890ab";
|
||||||
|
|
||||||
|
let mut cert = NebulaCertificate {
|
||||||
|
details: NebulaCertificateDetails {
|
||||||
|
name: "testing".to_string(),
|
||||||
|
ips: vec![
|
||||||
|
netmask!("10.1.1.1", "255.255.255.0"),
|
||||||
|
netmask!("10.1.1.2", "255.255.0.0"),
|
||||||
|
netmask!("10.1.1.3", "255.0.0.0")
|
||||||
|
],
|
||||||
|
subnets: vec![
|
||||||
|
netmask!("9.1.1.1", "255.255.255.128"),
|
||||||
|
netmask!("9.1.1.2", "255.255.255.0"),
|
||||||
|
netmask!("9.1.1.3", "255.255.0.0")
|
||||||
|
],
|
||||||
|
groups: vec!["test-group1".to_string(), "test-group2".to_string(), "test-group3".to_string()],
|
||||||
|
not_before: before,
|
||||||
|
not_after: after,
|
||||||
|
public_key: *pub_key,
|
||||||
|
is_ca: false,
|
||||||
|
issuer: "1234567890abcedfabcd1234567890ab".to_string(),
|
||||||
|
},
|
||||||
|
signature: b"1234567890abcedfghij1234567890ab".to_vec(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut csprng = OsRng;
|
||||||
|
let key = SigningKey::generate(&mut csprng);
|
||||||
|
|
||||||
|
assert!(cert.check_signature(&key.verifying_key()).is_err());
|
||||||
|
cert.sign(&key).unwrap();
|
||||||
|
assert!(cert.check_signature(&key.verifying_key()).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! netmask {
|
macro_rules! netmask {
|
||||||
($ip:expr,$mask:expr) => {
|
($ip:expr,$mask:expr) => {
|
||||||
|
|
Loading…
Reference in New Issue