added key domains

This commit is contained in:
Monica Moniot
2023-08-15 15:50:23 -04:00
parent e8b55a9b51
commit 3c2887aef1
4 changed files with 76 additions and 40 deletions
+2 -1
View File
@@ -9,4 +9,5 @@ version = "0.1.0"
serde = { version = "^1", features = ["derive"], default-features = false }
serde_cbor = { package = "serde_cbor_2", git = "https://github.com/kanidm/cbor", rev = "ab3296b35322aa5caa79a4ad9ce00a49c000864e" }
zerotier-common-utils = { git = "https://github.com/zerotier/common-utils.git", branch = "main" }
zerotier-crypto-glue = { git = "https://github.com/zerotier/crypto-glue.git", branch = "main" }
zerotier-crypto-glue = { git = "https://github.com/zerotier/crypto-glue.git", branch = "xoshiro" }
zeroize = { version = "1.6.0", features = ["zeroize_derive"], default-features = false }
+3 -1
View File
@@ -43,13 +43,15 @@ pub fn decode_11to8(s: &[u8]) -> Result<u64, InvalidParameterError> {
#[cfg(test)]
mod tests {
use zerotier_crypto_glue::random::{rand_core::RngCore, SecureRandom};
use super::*;
#[test]
fn base62_encode_decode() {
let mut tmp = String::with_capacity(16);
for _ in 0..10000 {
let r = zerotier_crypto_glue::random::next_u64_secure();
let r = SecureRandom.next_u64();
tmp.clear();
encode_8to11(r, &mut tmp);
assert_eq!(decode_11to8(tmp.as_bytes()).unwrap(), r);
+44 -26
View File
@@ -13,7 +13,7 @@ use std::str::FromStr;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use zerotier_common_utils::arrayvec::ArrayVec;
use zeroize::{Zeroize, ZeroizeOnDrop};
use zerotier_common_utils::base64;
use zerotier_common_utils::blob::Blob;
use zerotier_common_utils::error::InvalidParameterError;
@@ -24,6 +24,8 @@ use zerotier_crypto_glue::p384::*;
use crate::{base24, base62};
use crate::{ADDRESS_ERR, IDENTITY_ERR};
const IDENTITY_DOMAIN: &[u8] = b"zerotier_p384_identity";
// Implementation note: the addresses use u64 arrays that are actually treated as flat byte
// array memory arenas in order to optimize for fast lookup when these are used as map keys.
// This reduces the number of instructions required to perform equality comparisons and
@@ -396,15 +398,16 @@ pub struct Identity {
impl Identity {
fn locally_validate(&self) -> bool {
let mut sign_tmp = ArrayVec::<u8, 256>::new();
sign_tmp.push_slice(self.address.as_bytes());
sign_tmp.push_slice(&self.timestamp.to_be_bytes());
sign_tmp.push_slice(self.ecdh.as_bytes());
sign_tmp.push_slice(self.ecdsa.as_bytes());
self.address.is_valid()
&& self
.master_signing_key
.verify(sign_tmp.as_bytes(), &self.master_signature)
&& self.master_signing_key.verify_all(
IDENTITY_DOMAIN,
&[
&self.timestamp.to_be_bytes(),
self.ecdh.as_bytes(),
self.ecdsa.as_bytes(),
],
&self.master_signature,
)
}
/// Returns true if this identity should replace the other.
@@ -523,7 +526,11 @@ impl crate::Identity for Identity {
#[inline(always)]
fn verify_signature(&self, data: &[u8], signature: &[u8]) -> bool {
self.ecdsa.verify(data, signature)
if let Ok(sig) = signature.try_into() {
self.ecdsa.verify_raw(data, sig)
} else {
false
}
}
}
@@ -553,16 +560,22 @@ impl Clone for IdentitySecret {
}
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Zeroize, ZeroizeOnDrop)]
struct IdentitySecretSerialized {
#[zeroize(skip)]
a: Address,
#[zeroize(skip)]
pm: Blob<P384_PUBLIC_KEY_SIZE>,
sm: Option<Blob<P384_SECRET_KEY_SIZE>>,
#[zeroize(skip)]
ts: u64,
#[zeroize(skip)]
p0: Blob<P384_PUBLIC_KEY_SIZE>,
s0: Blob<P384_SECRET_KEY_SIZE>,
#[zeroize(skip)]
p1: Blob<P384_PUBLIC_KEY_SIZE>,
s1: Blob<P384_SECRET_KEY_SIZE>,
#[zeroize(skip)]
ms: Blob<P384_ECDSA_SIGNATURE_SIZE>,
}
@@ -571,21 +584,24 @@ impl Serialize for IdentitySecret {
where
S: Serializer,
{
IdentitySecretSerialized {
let mut tmp = IdentitySecretSerialized {
a: self.public.address,
pm: (*self.public.master_signing_key.as_bytes()).into(),
sm: self
.master_signing_key
.as_ref()
.map(|sk| (*sk.secret_key_bytes().as_bytes()).into()),
sm: None,
ts: self.public.timestamp,
p0: (*self.public.ecdh.as_bytes()).into(),
s0: (*self.ecdh.secret_key_bytes().as_bytes()).into(),
s0: Blob::default(),
p1: (*self.public.ecdsa.as_bytes()).into(),
s1: (*self.ecdsa.secret_key_bytes().as_bytes()).into(),
s1: Blob::default(),
ms: self.public.master_signature.into(),
};
self.ecdh.secret_key_bytes(&mut tmp.s0);
self.ecdsa.secret_key_bytes(&mut tmp.s1);
if let Some(ecdsa) = self.master_signing_key.as_ref() {
tmp.sm = Some(Blob::default());
ecdsa.secret_key_bytes(tmp.sm.as_mut().unwrap());
}
.serialize(serializer)
tmp.serialize(serializer)
}
}
@@ -651,11 +667,6 @@ impl crate::IdentitySecret for IdentitySecret {
let ecdh = P384KeyPair::generate();
let ecdsa = P384KeyPair::generate();
let mut sign_tmp = ArrayVec::<u8, 256>::new();
sign_tmp.push_slice(address.as_bytes());
sign_tmp.push_slice(&timestamp.to_be_bytes());
sign_tmp.push_slice(ecdh.public_key_bytes());
sign_tmp.push_slice(ecdsa.public_key_bytes());
Self {
public: Identity {
address,
@@ -663,7 +674,14 @@ impl crate::IdentitySecret for IdentitySecret {
timestamp,
ecdh: ecdh.to_public_key(),
ecdsa: ecdsa.to_public_key(),
master_signature: master_signing_key.sign(sign_tmp.as_bytes()),
master_signature: master_signing_key.sign_all(
IDENTITY_DOMAIN,
&[
&timestamp.to_be_bytes(),
ecdh.public_key_bytes(),
ecdsa.public_key_bytes(),
],
),
},
master_signing_key: Some(master_signing_key),
ecdh,
@@ -678,7 +696,7 @@ impl crate::IdentitySecret for IdentitySecret {
#[inline(always)]
fn sign(&self, data: &[u8]) -> Self::Signature {
self.ecdsa.sign(data)
self.ecdsa.sign_raw(data)
}
}
+27 -12
View File
@@ -14,6 +14,7 @@ use std::str::FromStr;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use zeroize::{Zeroize, ZeroizeOnDrop};
use zerotier_common_utils::blob::Blob;
use zerotier_common_utils::error::InvalidParameterError;
use zerotier_common_utils::hex;
@@ -305,8 +306,11 @@ impl ToString for IdentitySecret {
tmp.push_str(hex::to_string(&self.public.ecdh).as_str());
tmp.push_str(hex::to_string(&self.public.eddsa).as_str());
tmp.push(':');
tmp.push_str(hex::to_string(self.ecdh.secret_bytes().as_bytes()).as_str());
tmp.push_str(hex::to_string(self.eddsa.secret_bytes().as_bytes()).as_str());
let mut buf = [0u8; ED25519_SECRET_KEY_SIZE];
self.ecdh.secret_bytes(&mut buf);
tmp.push_str(hex::to_string(&buf).as_str());
self.eddsa.secret_bytes(&mut buf);
tmp.push_str(hex::to_string(&buf).as_str());
tmp
}
}
@@ -324,10 +328,16 @@ impl FromStr for IdentitySecret {
if secret_bytes.len() != C25519_SECRET_KEY_SIZE + ED25519_SECRET_KEY_SIZE {
return Err(IDENTITY_ERR);
}
let ecdh = X25519KeyPair::from_bytes(&public.ecdh, &secret_bytes.as_slice()[..C25519_SECRET_KEY_SIZE])
.ok_or(IDENTITY_ERR)?;
let eddsa = Ed25519KeyPair::from_bytes(&public.eddsa, &secret_bytes.as_slice()[C25519_SECRET_KEY_SIZE..])
.ok_or(IDENTITY_ERR)?;
let ecdh = X25519KeyPair::from_bytes(
&public.ecdh,
&secret_bytes.as_slice()[..C25519_SECRET_KEY_SIZE].try_into().unwrap(),
)
.ok_or(IDENTITY_ERR)?;
let eddsa = Ed25519KeyPair::from_bytes(
&public.eddsa,
&secret_bytes.as_slice()[C25519_SECRET_KEY_SIZE..].try_into().unwrap(),
)
.ok_or(IDENTITY_ERR)?;
return Ok(Self { public, ecdh, eddsa });
}
}
@@ -385,11 +395,14 @@ impl crate::IdentitySecret for IdentitySecret {
}
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Zeroize, ZeroizeOnDrop)]
struct IdentitySecretSerialized {
#[zeroize(skip)]
a: Address,
#[zeroize(skip)]
p0: Blob<C25519_PUBLIC_KEY_SIZE>,
s0: Blob<C25519_SECRET_KEY_SIZE>,
#[zeroize(skip)]
p1: Blob<ED25519_PUBLIC_KEY_SIZE>,
s1: Blob<ED25519_SECRET_KEY_SIZE>,
}
@@ -399,14 +412,16 @@ impl Serialize for IdentitySecret {
where
S: Serializer,
{
IdentitySecretSerialized {
let mut tmp = IdentitySecretSerialized {
a: self.public.address,
p0: self.public.ecdh.into(),
s0: (*self.ecdh.secret_bytes().as_bytes()).into(),
s0: Blob::default(),
p1: self.public.eddsa.into(),
s1: (*self.eddsa.secret_bytes().as_bytes()).into(),
}
.serialize(serializer)
s1: Blob::default(),
};
self.ecdh.secret_bytes(&mut tmp.s0);
self.eddsa.secret_bytes(&mut tmp.s1);
tmp.serialize(serializer)
}
}