2021-01-15 19:37:06 +03:00
|
|
|
|
/*
|
|
|
|
|
* Copyright 2020 Fluence Labs Limited
|
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
2021-02-09 15:50:21 +03:00
|
|
|
|
use crate::certificate::CertificateError::{
|
2021-04-15 14:00:27 +03:00
|
|
|
|
CertificateLengthError, DecodeError, DecodeTrustError, ExpirationError,
|
2021-02-11 15:10:18 +03:00
|
|
|
|
IncorrectCertificateFormat, KeyInCertificateError, MalformedRoot, NoTrustedRoot,
|
|
|
|
|
VerificationError,
|
2021-02-09 13:26:44 +03:00
|
|
|
|
};
|
2021-04-15 14:00:27 +03:00
|
|
|
|
use crate::trust::{Trust, TrustError};
|
2021-08-12 15:49:03 +03:00
|
|
|
|
use fluence_keypair::key_pair::KeyPair;
|
|
|
|
|
use fluence_keypair::public_key::PublicKey;
|
2021-01-15 19:37:06 +03:00
|
|
|
|
use std::str::FromStr;
|
|
|
|
|
use std::time::Duration;
|
2021-02-09 13:26:44 +03:00
|
|
|
|
use thiserror::Error as ThisError;
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
/// Serialization format of a certificate.
|
|
|
|
|
/// TODO
|
|
|
|
|
const FORMAT: &[u8; 2] = &[0, 0];
|
|
|
|
|
/// Serialization format version of a certificate.
|
|
|
|
|
/// TODO
|
|
|
|
|
const VERSION: &[u8; 4] = &[0, 0, 0, 0];
|
2021-04-15 14:00:27 +03:00
|
|
|
|
const TRUST_NUMBER_LEN: usize = 1;
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
/// Chain of trusts started from self-signed root trust.
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
|
pub struct Certificate {
|
|
|
|
|
pub chain: Vec<Trust>,
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-09 13:26:44 +03:00
|
|
|
|
#[derive(ThisError, Debug)]
|
2021-02-09 15:50:21 +03:00
|
|
|
|
pub enum CertificateError {
|
2021-02-11 15:10:18 +03:00
|
|
|
|
#[error("Incorrect format of the certificate: {0}")]
|
|
|
|
|
IncorrectCertificateFormat(String),
|
|
|
|
|
#[error("Incorrect length of an array. Should be 2 bytes of a format, 4 bytes of a version and 104 bytes for each trust")]
|
|
|
|
|
IncorrectByteLength,
|
|
|
|
|
#[error("Error while decoding a trust in a certificate: {0}")]
|
2021-02-15 13:01:22 +03:00
|
|
|
|
DecodeError(#[source] TrustError),
|
2021-02-09 14:31:41 +03:00
|
|
|
|
#[error("Certificate is expired. Issued at {issued_at} and expired at {expires_at}")]
|
2021-01-28 11:57:43 +03:00
|
|
|
|
ExpirationError {
|
|
|
|
|
expires_at: String,
|
2021-02-09 13:26:44 +03:00
|
|
|
|
issued_at: String,
|
2021-01-28 11:57:43 +03:00
|
|
|
|
},
|
2021-02-09 13:26:44 +03:00
|
|
|
|
#[error("Certificate does not contain a trusted root.")]
|
|
|
|
|
NoTrustedRoot,
|
|
|
|
|
#[error("Root trust did not pass verification: {0}")]
|
2021-02-15 13:01:22 +03:00
|
|
|
|
MalformedRoot(#[source] TrustError),
|
2021-02-09 13:26:44 +03:00
|
|
|
|
#[error("There is no `issued_by` public key in a certificate")]
|
2021-01-28 11:57:43 +03:00
|
|
|
|
KeyInCertificateError,
|
2021-02-09 13:26:44 +03:00
|
|
|
|
#[error("The certificate must have at least 1 trust")]
|
2021-01-28 11:57:43 +03:00
|
|
|
|
CertificateLengthError,
|
2021-02-11 15:10:18 +03:00
|
|
|
|
#[error("Cannot convert trust number {0} from string: {1}")]
|
2021-02-15 13:01:22 +03:00
|
|
|
|
DecodeTrustError(usize, #[source] TrustError),
|
2021-02-09 13:26:44 +03:00
|
|
|
|
#[error("Trust {0} in chain did not pass verification: {1}")]
|
2021-02-15 13:01:22 +03:00
|
|
|
|
VerificationError(usize, #[source] TrustError),
|
2021-02-11 15:10:18 +03:00
|
|
|
|
#[error("there cannot be paths without any nodes after adding verified certificates")]
|
|
|
|
|
Unexpected,
|
2021-02-09 15:50:21 +03:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 19:37:06 +03:00
|
|
|
|
impl Certificate {
|
|
|
|
|
pub fn new_unverified(chain: Vec<Trust>) -> Self {
|
|
|
|
|
Self { chain }
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-06 18:13:08 +03:00
|
|
|
|
pub fn new_from_root_trust(root_trust: Trust, issued_trust: Trust, cur_time: Duration) -> Result<Self, CertificateError> {
|
|
|
|
|
Trust::verify(&root_trust, &root_trust.issued_for, cur_time).map_err(MalformedRoot)?;
|
|
|
|
|
Trust::verify(&issued_trust, &root_trust.issued_for, cur_time).map_err(|e| VerificationError(1, e))?;
|
|
|
|
|
|
|
|
|
|
Ok(Self { chain: vec![root_trust, issued_trust] })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn issue_with_trust(issued_by: PublicKey, trust: Trust, extend_cert: &Certificate, cur_time: Duration) -> Result<Self, CertificateError> {
|
|
|
|
|
if trust.expires_at.lt(&trust.issued_at) {
|
|
|
|
|
return Err(ExpirationError {
|
|
|
|
|
expires_at: format!("{:?}", trust.expires_at),
|
|
|
|
|
issued_at: format!("{:?}", trust.issued_at),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Certificate::verify(extend_cert, &[extend_cert.chain[0].issued_for.clone()], cur_time)?;
|
|
|
|
|
// check if `issued_by` is allowed to issue a certificate (i.e., there’s a trust for it in a chain)
|
|
|
|
|
let mut previous_trust_num: i32 = -1;
|
|
|
|
|
for pk_id in 0..extend_cert.chain.len() {
|
|
|
|
|
if extend_cert.chain[pk_id].issued_for == issued_by {
|
|
|
|
|
previous_trust_num = pk_id as i32;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if previous_trust_num == -1 {
|
|
|
|
|
return Err(KeyInCertificateError);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// splitting old chain to add new trust after given public key
|
|
|
|
|
let mut new_chain = extend_cert
|
|
|
|
|
.chain
|
|
|
|
|
.split_at((previous_trust_num + 1) as usize)
|
|
|
|
|
.0
|
|
|
|
|
.to_vec();
|
|
|
|
|
|
|
|
|
|
new_chain.push(trust);
|
|
|
|
|
|
|
|
|
|
Ok(Self { chain: new_chain })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-01-15 19:37:06 +03:00
|
|
|
|
/// Creates new certificate with root trust (self-signed public key) from a key pair.
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
pub fn issue_root(
|
|
|
|
|
root_kp: &KeyPair,
|
|
|
|
|
for_pk: PublicKey,
|
|
|
|
|
expires_at: Duration,
|
|
|
|
|
issued_at: Duration,
|
|
|
|
|
) -> Self {
|
|
|
|
|
let root_expiration = Duration::from_secs(u64::max_value());
|
|
|
|
|
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let root_trust = Trust::create(root_kp, root_kp.public(), root_expiration, issued_at);
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
let trust = Trust::create(root_kp, for_pk, expires_at, issued_at);
|
|
|
|
|
|
|
|
|
|
let chain = vec![root_trust, trust];
|
|
|
|
|
Self { chain }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Adds a new trust into chain of trust in certificate.
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
pub fn issue(
|
|
|
|
|
issued_by: &KeyPair,
|
|
|
|
|
for_pk: PublicKey,
|
|
|
|
|
extend_cert: &Certificate,
|
|
|
|
|
expires_at: Duration,
|
|
|
|
|
issued_at: Duration,
|
|
|
|
|
cur_time: Duration,
|
2021-02-09 15:50:21 +03:00
|
|
|
|
) -> Result<Self, CertificateError> {
|
2021-01-15 19:37:06 +03:00
|
|
|
|
if expires_at.lt(&issued_at) {
|
2021-02-09 13:26:44 +03:00
|
|
|
|
return Err(ExpirationError {
|
|
|
|
|
expires_at: format!("{:?}", expires_at),
|
|
|
|
|
issued_at: format!("{:?}", issued_at),
|
|
|
|
|
});
|
2021-01-15 19:37:06 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// first, verify given certificate
|
2021-04-15 14:00:27 +03:00
|
|
|
|
Certificate::verify(extend_cert, &[extend_cert.chain[0].issued_for.clone()], cur_time)?;
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let issued_by_pk = issued_by.public();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
// check if `issued_by_pk` is allowed to issue a certificate (i.e., there’s a trust for it in a chain)
|
|
|
|
|
let mut previous_trust_num: i32 = -1;
|
|
|
|
|
for pk_id in 0..extend_cert.chain.len() {
|
|
|
|
|
if extend_cert.chain[pk_id].issued_for == issued_by_pk {
|
|
|
|
|
previous_trust_num = pk_id as i32;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if previous_trust_num == -1 {
|
2021-02-09 13:26:44 +03:00
|
|
|
|
return Err(KeyInCertificateError);
|
2021-01-15 19:37:06 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// splitting old chain to add new trust after given public key
|
|
|
|
|
let mut new_chain = extend_cert
|
|
|
|
|
.chain
|
|
|
|
|
.split_at((previous_trust_num + 1) as usize)
|
|
|
|
|
.0
|
|
|
|
|
.to_vec();
|
|
|
|
|
|
|
|
|
|
let trust = Trust::create(issued_by, for_pk, expires_at, issued_at);
|
|
|
|
|
|
|
|
|
|
new_chain.push(trust);
|
|
|
|
|
|
|
|
|
|
Ok(Self { chain: new_chain })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Verifies that a certificate is valid and you trust to this certificate.
|
|
|
|
|
pub fn verify(
|
|
|
|
|
cert: &Certificate,
|
|
|
|
|
trusted_roots: &[PublicKey],
|
|
|
|
|
cur_time: Duration,
|
2021-02-09 15:50:21 +03:00
|
|
|
|
) -> Result<(), CertificateError> {
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let chain = &cert.chain;
|
|
|
|
|
|
|
|
|
|
if chain.is_empty() {
|
2021-02-09 13:26:44 +03:00
|
|
|
|
return Err(CertificateLengthError);
|
2021-01-15 19:37:06 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check root trust and its existence in trusted roots list
|
|
|
|
|
let root = &chain[0];
|
2021-02-11 15:16:40 +03:00
|
|
|
|
Trust::verify(root, &root.issued_for, cur_time).map_err(MalformedRoot)?;
|
2021-01-15 19:37:06 +03:00
|
|
|
|
if !trusted_roots.contains(&root.issued_for) {
|
2021-02-09 13:26:44 +03:00
|
|
|
|
return Err(NoTrustedRoot);
|
2021-01-15 19:37:06 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check if every element in a chain is not expired and has the correct signature
|
|
|
|
|
for trust_id in (1..chain.len()).rev() {
|
|
|
|
|
let trust = &chain[trust_id];
|
|
|
|
|
|
|
|
|
|
let trust_giver = &chain[trust_id - 1];
|
|
|
|
|
|
2021-02-09 13:26:44 +03:00
|
|
|
|
Trust::verify(trust, &trust_giver.issued_for, cur_time)
|
2021-02-11 15:10:18 +03:00
|
|
|
|
.map_err(|e| VerificationError(trust_id, e))?;
|
2021-01-15 19:37:06 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Convert certificate to byte format
|
2021-04-15 14:00:27 +03:00
|
|
|
|
/// 2 format + 4 version + 1 trusts number + ((1 trust size byte + trust) for each trust)
|
2021-01-15 19:37:06 +03:00
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
pub fn encode(&self) -> Vec<u8> {
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let mut encoded = Vec::new();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
encoded.extend_from_slice(FORMAT);
|
|
|
|
|
encoded.extend_from_slice(VERSION);
|
2021-04-15 14:00:27 +03:00
|
|
|
|
encoded.push(self.chain.len() as u8);
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
for t in &self.chain {
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let trust = t.encode();
|
|
|
|
|
encoded.push(trust.len() as u8);
|
|
|
|
|
encoded.extend(trust);
|
2021-01-15 19:37:06 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
encoded
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-15 14:00:27 +03:00
|
|
|
|
fn check_arr_len(arr: &[u8], check_len: usize) -> Result<(), CertificateError> {
|
|
|
|
|
if arr.len() < check_len {
|
|
|
|
|
Err(CertificateLengthError)
|
|
|
|
|
} else {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 19:37:06 +03:00
|
|
|
|
#[allow(dead_code)]
|
2021-02-09 15:50:21 +03:00
|
|
|
|
pub fn decode(arr: &[u8]) -> Result<Self, CertificateError> {
|
2021-04-15 14:00:27 +03:00
|
|
|
|
// TODO do match different formats and versions
|
|
|
|
|
Self::check_arr_len(arr, FORMAT.len() + VERSION.len() + TRUST_NUMBER_LEN)?;
|
|
|
|
|
let mut offset = 0;
|
|
|
|
|
let _format = &arr[offset..offset + FORMAT.len()];
|
|
|
|
|
offset += FORMAT.len();
|
|
|
|
|
|
|
|
|
|
let _version = &arr[offset..offset + VERSION.len()];
|
|
|
|
|
offset += VERSION.len();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let number_of_trusts = arr[offset] as usize;
|
|
|
|
|
offset += TRUST_NUMBER_LEN;
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
if number_of_trusts < 2 {
|
2021-02-09 13:26:44 +03:00
|
|
|
|
return Err(CertificateLengthError);
|
2021-01-15 19:37:06 +03:00
|
|
|
|
}
|
|
|
|
|
let mut chain = Vec::with_capacity(number_of_trusts);
|
|
|
|
|
|
2021-04-15 14:00:27 +03:00
|
|
|
|
for _ in 0..number_of_trusts {
|
|
|
|
|
Self::check_arr_len(arr, offset + 1)?;
|
|
|
|
|
let trust_len = arr[offset] as usize;
|
|
|
|
|
let from = offset + 1;
|
|
|
|
|
let to = from + trust_len;
|
|
|
|
|
Self::check_arr_len(arr, to)?;
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let slice = &arr[from..to];
|
2021-02-11 15:16:40 +03:00
|
|
|
|
let t = Trust::decode(slice).map_err(DecodeError)?;
|
2021-01-15 19:37:06 +03:00
|
|
|
|
chain.push(t);
|
2021-04-15 14:00:27 +03:00
|
|
|
|
offset += 1 + trust_len;
|
2021-01-15 19:37:06 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(Self { chain })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Display for Certificate {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
writeln!(f, "{}", bs58::encode(FORMAT).into_string())?;
|
|
|
|
|
writeln!(f, "{}", bs58::encode(VERSION).into_string())?;
|
|
|
|
|
for trust in self.chain.iter() {
|
|
|
|
|
writeln!(f, "{}", trust.to_string())?;
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl FromStr for Certificate {
|
2021-02-09 15:50:21 +03:00
|
|
|
|
type Err = CertificateError;
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
|
let str_lines: Vec<&str> = s.lines().collect();
|
|
|
|
|
|
|
|
|
|
// TODO for future purposes
|
|
|
|
|
let _format = str_lines[0];
|
|
|
|
|
let _version = str_lines[1];
|
|
|
|
|
|
|
|
|
|
if (str_lines.len() - 2) % 4 != 0 {
|
2021-02-11 15:10:18 +03:00
|
|
|
|
return Err(IncorrectCertificateFormat(s.to_string()));
|
2021-01-15 19:37:06 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let num_of_trusts = (str_lines.len() - 2) / 4;
|
|
|
|
|
let mut trusts = Vec::with_capacity(num_of_trusts);
|
|
|
|
|
|
|
|
|
|
for i in (2..str_lines.len()).step_by(4) {
|
|
|
|
|
let trust = Trust::convert_from_strings(
|
|
|
|
|
str_lines[i],
|
|
|
|
|
str_lines[i + 1],
|
|
|
|
|
str_lines[i + 2],
|
|
|
|
|
str_lines[i + 3],
|
2021-02-09 13:26:44 +03:00
|
|
|
|
)
|
2021-04-15 14:00:27 +03:00
|
|
|
|
.map_err(|e| DecodeTrustError(i, e))?;
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
trusts.push(trust);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(Self::new_unverified(trusts))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
use crate::misc::current_time;
|
2021-08-12 15:49:03 +03:00
|
|
|
|
use fluence_keypair::KeyPair;
|
2021-01-19 17:25:28 +03:00
|
|
|
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
pub fn one_second() -> Duration {
|
|
|
|
|
Duration::from_secs(1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn one_minute() -> Duration {
|
|
|
|
|
Duration::from_secs(60)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn one_year() -> Duration {
|
|
|
|
|
Duration::from_secs(31_557_600)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2021-04-15 14:00:27 +03:00
|
|
|
|
pub fn test_string_encoding_decoding_ed25519() {
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let (_root_kp, second_kp, cert) = generate_root_cert();
|
|
|
|
|
|
|
|
|
|
let cur_time = current_time();
|
|
|
|
|
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let third_kp = KeyPair::generate_ed25519();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
let new_cert = Certificate::issue(
|
|
|
|
|
&second_kp,
|
2021-01-19 18:28:13 +03:00
|
|
|
|
third_kp.public(),
|
2021-01-15 19:37:06 +03:00
|
|
|
|
&cert,
|
|
|
|
|
cur_time.checked_add(one_second()).unwrap(),
|
|
|
|
|
cur_time,
|
|
|
|
|
cur_time,
|
|
|
|
|
)
|
2021-04-15 14:00:27 +03:00
|
|
|
|
.unwrap();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
let serialized = new_cert.to_string();
|
|
|
|
|
let deserialized = Certificate::from_str(&serialized);
|
|
|
|
|
|
|
|
|
|
assert!(deserialized.is_ok());
|
|
|
|
|
let after_cert = deserialized.unwrap();
|
|
|
|
|
assert_eq!(&new_cert.chain[0], &after_cert.chain[0]);
|
|
|
|
|
assert_eq!(&new_cert, &after_cert);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2021-04-15 14:00:27 +03:00
|
|
|
|
pub fn test_serialization_deserialization_ed25519() {
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let (_root_kp, second_kp, cert) = generate_root_cert();
|
|
|
|
|
|
|
|
|
|
let cur_time = current_time();
|
|
|
|
|
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let third_kp = KeyPair::generate_ed25519();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
let new_cert = Certificate::issue(
|
|
|
|
|
&second_kp,
|
2021-01-19 18:28:13 +03:00
|
|
|
|
third_kp.public(),
|
2021-01-15 19:37:06 +03:00
|
|
|
|
&cert,
|
|
|
|
|
cur_time.checked_add(one_second()).unwrap(),
|
|
|
|
|
cur_time,
|
|
|
|
|
cur_time,
|
|
|
|
|
)
|
2021-04-15 14:00:27 +03:00
|
|
|
|
.unwrap();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
let serialized = new_cert.encode();
|
|
|
|
|
let deserialized = Certificate::decode(serialized.as_slice());
|
|
|
|
|
|
|
|
|
|
assert!(deserialized.is_ok());
|
|
|
|
|
let after_cert = deserialized.unwrap();
|
|
|
|
|
assert_eq!(&new_cert.chain[0], &after_cert.chain[0]);
|
|
|
|
|
assert_eq!(&new_cert, &after_cert);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2021-04-15 14:00:27 +03:00
|
|
|
|
fn test_small_chain_ed25519() {
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let bad_cert = Certificate { chain: Vec::new() };
|
|
|
|
|
|
|
|
|
|
let check = Certificate::verify(&bad_cert, &[], current_time());
|
|
|
|
|
assert!(check.is_err());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn generate_root_cert() -> (KeyPair, KeyPair, Certificate) {
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let root_kp = KeyPair::generate_ed25519();
|
|
|
|
|
let second_kp = KeyPair::generate_ed25519();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
let cur_time = current_time();
|
|
|
|
|
|
|
|
|
|
(
|
|
|
|
|
root_kp.clone(),
|
|
|
|
|
second_kp.clone(),
|
|
|
|
|
Certificate::issue_root(
|
|
|
|
|
&root_kp,
|
2021-04-15 14:00:27 +03:00
|
|
|
|
second_kp.public(),
|
2021-01-15 19:37:06 +03:00
|
|
|
|
cur_time.checked_add(one_year()).unwrap(),
|
|
|
|
|
cur_time,
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2021-04-15 14:00:27 +03:00
|
|
|
|
fn test_issue_cert_ed25519() {
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let (root_kp, second_kp, cert) = generate_root_cert();
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let trusted_roots = [root_kp.public()];
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
// we don't need nanos for serialization, etc
|
|
|
|
|
let cur_time = Duration::from_secs(
|
|
|
|
|
SystemTime::now()
|
|
|
|
|
.duration_since(UNIX_EPOCH)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.as_secs() as u64,
|
|
|
|
|
);
|
|
|
|
|
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let third_kp = KeyPair::generate_ed25519();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
let new_cert = Certificate::issue(
|
|
|
|
|
&second_kp,
|
2021-01-19 18:28:13 +03:00
|
|
|
|
third_kp.public(),
|
2021-01-15 19:37:06 +03:00
|
|
|
|
&cert,
|
|
|
|
|
cur_time.checked_add(one_year()).unwrap(),
|
|
|
|
|
cur_time,
|
|
|
|
|
cur_time,
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(new_cert.is_ok(), true);
|
|
|
|
|
let new_cert = new_cert.unwrap();
|
2021-09-06 18:13:08 +03:00
|
|
|
|
|
2021-01-15 19:37:06 +03:00
|
|
|
|
println!("cert is\n{}", new_cert.to_string());
|
|
|
|
|
|
|
|
|
|
assert_eq!(new_cert.chain.len(), 3);
|
2021-04-15 14:00:27 +03:00
|
|
|
|
assert_eq!(new_cert.chain[0].issued_for, root_kp.public());
|
|
|
|
|
assert_eq!(new_cert.chain[1].issued_for, second_kp.public());
|
|
|
|
|
assert_eq!(new_cert.chain[2].issued_for, third_kp.public());
|
2021-01-15 19:37:06 +03:00
|
|
|
|
assert!(Certificate::verify(&new_cert, &trusted_roots, cur_time).is_ok());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2021-04-15 14:00:27 +03:00
|
|
|
|
fn test_cert_expiration_ed25519() {
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let (root_kp, second_kp, cert) = generate_root_cert();
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let trusted_roots = [root_kp.public()];
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
|
|
|
|
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let third_kp = KeyPair::generate_ed25519();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
let new_cert = Certificate::issue(
|
|
|
|
|
&second_kp,
|
2021-01-19 18:28:13 +03:00
|
|
|
|
third_kp.public(),
|
2021-01-15 19:37:06 +03:00
|
|
|
|
&cert,
|
|
|
|
|
cur_time.checked_sub(one_second()).unwrap(),
|
|
|
|
|
cur_time.checked_sub(one_minute()).unwrap(),
|
|
|
|
|
cur_time,
|
|
|
|
|
)
|
2021-04-15 14:00:27 +03:00
|
|
|
|
.unwrap();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
assert!(Certificate::verify(&new_cert, &trusted_roots, cur_time).is_err());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2021-04-15 14:00:27 +03:00
|
|
|
|
fn test_issue_in_chain_tail_ed25519() {
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let (root_kp, second_kp, cert) = generate_root_cert();
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let trusted_roots = [root_kp.public()];
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
|
|
|
|
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let third_kp = KeyPair::generate_ed25519();
|
|
|
|
|
let fourth_kp = KeyPair::generate_ed25519();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
let new_cert = Certificate::issue(
|
|
|
|
|
&second_kp,
|
2021-01-19 18:28:13 +03:00
|
|
|
|
third_kp.public(),
|
2021-01-15 19:37:06 +03:00
|
|
|
|
&cert,
|
|
|
|
|
cur_time.checked_add(one_second()).unwrap(),
|
|
|
|
|
cur_time,
|
|
|
|
|
cur_time,
|
|
|
|
|
)
|
2021-04-15 14:00:27 +03:00
|
|
|
|
.unwrap();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let new_cert = Certificate::issue(
|
|
|
|
|
&third_kp,
|
2021-01-19 18:28:13 +03:00
|
|
|
|
fourth_kp.public(),
|
2021-01-15 19:37:06 +03:00
|
|
|
|
&new_cert,
|
|
|
|
|
cur_time.checked_add(one_second()).unwrap(),
|
|
|
|
|
cur_time,
|
|
|
|
|
cur_time,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
assert_eq!(new_cert.is_ok(), true);
|
|
|
|
|
let new_cert = new_cert.unwrap();
|
|
|
|
|
|
|
|
|
|
assert_eq!(new_cert.chain.len(), 4);
|
2021-04-15 14:00:27 +03:00
|
|
|
|
assert_eq!(new_cert.chain[0].issued_for, root_kp.public());
|
|
|
|
|
assert_eq!(new_cert.chain[1].issued_for, second_kp.public());
|
|
|
|
|
assert_eq!(new_cert.chain[2].issued_for, third_kp.public());
|
|
|
|
|
assert_eq!(new_cert.chain[3].issued_for, fourth_kp.public());
|
2021-01-15 19:37:06 +03:00
|
|
|
|
assert!(Certificate::verify(&new_cert, &trusted_roots, cur_time).is_ok());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2021-04-15 14:00:27 +03:00
|
|
|
|
fn test_issue_in_chain_body_ed25519() {
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let (root_kp, second_kp, cert) = generate_root_cert();
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let trusted_roots = [root_kp.public()];
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
|
|
|
|
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let third_kp = KeyPair::generate_ed25519();
|
|
|
|
|
let fourth_kp = KeyPair::generate_ed25519();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
let new_cert = Certificate::issue(
|
|
|
|
|
&second_kp,
|
2021-01-19 18:28:13 +03:00
|
|
|
|
third_kp.public(),
|
2021-01-15 19:37:06 +03:00
|
|
|
|
&cert,
|
|
|
|
|
cur_time.checked_add(one_second()).unwrap(),
|
|
|
|
|
cur_time,
|
|
|
|
|
cur_time,
|
|
|
|
|
)
|
2021-04-15 14:00:27 +03:00
|
|
|
|
.unwrap();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let new_cert = Certificate::issue(
|
|
|
|
|
&second_kp,
|
2021-01-19 18:28:13 +03:00
|
|
|
|
fourth_kp.public(),
|
2021-01-15 19:37:06 +03:00
|
|
|
|
&new_cert,
|
|
|
|
|
cur_time.checked_add(one_second()).unwrap(),
|
|
|
|
|
cur_time,
|
|
|
|
|
cur_time,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
assert_eq!(new_cert.is_ok(), true);
|
|
|
|
|
let new_cert = new_cert.unwrap();
|
|
|
|
|
|
|
|
|
|
assert_eq!(new_cert.chain.len(), 3);
|
2021-04-15 14:00:27 +03:00
|
|
|
|
assert_eq!(new_cert.chain[0].issued_for, root_kp.public());
|
|
|
|
|
assert_eq!(new_cert.chain[1].issued_for, second_kp.public());
|
|
|
|
|
assert_eq!(new_cert.chain[2].issued_for, fourth_kp.public());
|
2021-01-15 19:37:06 +03:00
|
|
|
|
assert!(Certificate::verify(&new_cert, &trusted_roots, cur_time).is_ok());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2021-04-15 14:00:27 +03:00
|
|
|
|
fn test_no_cert_in_chain_ed25519() {
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let (_root_kp, _second_kp, cert) = generate_root_cert();
|
|
|
|
|
let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
|
|
|
|
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let bad_kp = KeyPair::generate_ed25519();
|
2021-01-15 19:37:06 +03:00
|
|
|
|
let new_cert_bad = Certificate::issue(
|
|
|
|
|
&bad_kp,
|
2021-01-19 18:28:13 +03:00
|
|
|
|
bad_kp.public(),
|
2021-01-15 19:37:06 +03:00
|
|
|
|
&cert,
|
|
|
|
|
cur_time.checked_add(one_second()).unwrap(),
|
|
|
|
|
cur_time,
|
|
|
|
|
cur_time,
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(new_cert_bad.is_err(), true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_no_trusted_root_in_chain() {
|
|
|
|
|
let (_root_kp, second_kp, cert) = generate_root_cert();
|
|
|
|
|
let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
|
|
|
|
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let trusted_roots = [second_kp.public()];
|
2021-01-15 19:37:06 +03:00
|
|
|
|
assert!(Certificate::verify(&cert, &trusted_roots, cur_time).is_err());
|
|
|
|
|
assert!(Certificate::verify(&cert, &[], cur_time).is_err());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_forged_cert() {
|
|
|
|
|
let (root_kp, _second_kp, cert) = generate_root_cert();
|
|
|
|
|
let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let trusted_roots = [root_kp.public()];
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
// forged cert
|
|
|
|
|
let mut bad_chain = cert.chain;
|
|
|
|
|
bad_chain.remove(0);
|
|
|
|
|
let bad_cert = Certificate { chain: bad_chain };
|
|
|
|
|
|
|
|
|
|
assert!(Certificate::verify(&bad_cert, &trusted_roots, cur_time).is_err());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_generate_root_cert() {
|
|
|
|
|
let (root_kp, second_kp, cert) = generate_root_cert();
|
|
|
|
|
let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
|
|
|
|
|
2021-04-15 14:00:27 +03:00
|
|
|
|
let trusted_roots = [root_kp.public()];
|
2021-01-15 19:37:06 +03:00
|
|
|
|
|
|
|
|
|
assert_eq!(cert.chain.len(), 2);
|
2021-04-15 14:00:27 +03:00
|
|
|
|
assert_eq!(cert.chain[0].issued_for, root_kp.public());
|
|
|
|
|
assert_eq!(cert.chain[1].issued_for, second_kp.public());
|
2021-01-15 19:37:06 +03:00
|
|
|
|
assert!(Certificate::verify(&cert, &trusted_roots, cur_time).is_ok());
|
|
|
|
|
}
|
|
|
|
|
}
|