From b123891bd80043d1313e48979c8381fc37b733fa Mon Sep 17 00:00:00 2001 From: Monica Moniot Date: Mon, 26 Feb 2024 12:28:44 -0500 Subject: [PATCH] added identifier --- Cargo.toml | 2 +- src/p384/address.rs | 13 --- src/p384/identifier.rs | 170 ++++++++++++++++++++++++++++++++++++ src/p384/identity.rs | 7 ++ src/p384/identity_secret.rs | 7 ++ src/p384/mod.rs | 5 +- src/p384/short_address.rs | 7 ++ 7 files changed, 195 insertions(+), 16 deletions(-) create mode 100644 src/p384/identifier.rs diff --git a/Cargo.toml b/Cargo.toml index 824346c..e794939 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ authors = ["ZeroTier, Inc. "] edition = "2021" license = "MPL-2.0" name = "zerotier-identity" -version = "0.1.1" +version = "0.1.2" [dependencies] serde = { version = "1.0.183", features = ["derive"], default-features = false } diff --git a/src/p384/address.rs b/src/p384/address.rs index fc7a019..82635b7 100644 --- a/src/p384/address.rs +++ b/src/p384/address.rs @@ -5,20 +5,7 @@ * (c) ZeroTier, Inc. * https://www.zerotier.com/ */ - -use std::fmt::Debug; -use std::hash::Hash; -use std::mem::{size_of, transmute}; - -use serde::{Deserialize, Deserializer, Serialize, Serializer}; - use crate::p384::*; -use zerotier_common_utils::blob::Blob; -use zerotier_common_utils::error::InvalidParameterError; -use zerotier_common_utils::tofrombytes::ToFromBytes; - -use crate::base62; -use crate::ADDRESS_ERR; // 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. diff --git a/src/p384/identifier.rs b/src/p384/identifier.rs new file mode 100644 index 0000000..5932eb3 --- /dev/null +++ b/src/p384/identifier.rs @@ -0,0 +1,170 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ + */ +use crate::p384::*; + +#[derive(Debug, Clone, Hash)] +pub enum PeerIdentifier { + Identity(Identity), + Address(Address), + Short(ShortAddress), +} +#[derive(Debug, Clone, Hash)] +pub enum PeerIdentifierRef<'a> { + Identity(&'a Identity), + Address(&'a Address), + Short(ShortAddress), +} + +impl PeerIdentifier { + pub fn matches(&self, identity: &Identity) -> bool { + match self { + PeerIdentifier::Identity(id) => id.eq(identity), + PeerIdentifier::Address(id) => identity.address.eq(id), + PeerIdentifier::Short(id) => identity.address.prefix().eq(id), + } + } + + pub fn prefix(&self) -> &ShortAddress { + match self { + PeerIdentifier::Identity(id) => id.address.prefix(), + PeerIdentifier::Address(id) => id.prefix(), + PeerIdentifier::Short(id) => id, + } + } + + pub fn address(&self) -> AnyAddress { + match self { + PeerIdentifier::Identity(id) => id.address.into(), + PeerIdentifier::Address(id) => id.into(), + PeerIdentifier::Short(id) => id.into(), + } + } + + /// Returns `true` if `other` contains the most complete version of the identity between + /// `self` and `other`. + /// Otherwise returns `false`. + /// This function will debug panic if `self` and `other` are not identifiers for the same peer. + /// The caller must check for equality before calling this function. + /// TODO: make this function take into account identity lifetime. + pub fn upgrade_check(&self, other: &Self) -> bool { + debug_assert_eq!(self, other); + use PeerIdentifier::*; + match (self, other) { + (Identity(_), _) => false, + (_, Identity(_)) => true, + (Short(_), Address(_)) => true, + _ => false, + } + } +} +/// Does not preserve transitivity. +impl std::cmp::PartialEq for PeerIdentifier { + fn eq(&self, other: &Self) -> bool { + use PeerIdentifier::*; + match (self, other) { + (Identity(identity), id) | (id, Identity(identity)) => id.matches(identity), + (Address(addr0), Address(addr1)) => addr0.eq(addr1), + (Address(addr0), Short(addr1)) => addr0.prefix().eq(addr1), + (Short(addr0), Address(addr1)) => addr0.eq(addr1.prefix()), + (Short(addr0), Short(addr1)) => addr0.eq(addr1), + } + } +} +impl From
for PeerIdentifier { + fn from(value: Address) -> Self { + Self::Address(value) + } +} +impl From for PeerIdentifier { + fn from(value: ShortAddress) -> Self { + Self::Short(value) + } +} +impl From<&Address> for PeerIdentifier { + fn from(value: &Address) -> Self { + Self::Address(*value) + } +} +impl From<&ShortAddress> for PeerIdentifier { + fn from(value: &ShortAddress) -> Self { + Self::Short(*value) + } +} + +impl From for PeerIdentifier { + fn from(value: Identity) -> Self { + Self::Identity(value) + } +} + +#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, Copy, Hash)] +pub enum AnyAddress { + Address(Address), + Short(ShortAddress), +} +impl AnyAddress { + pub fn matches(&self, identity: &Identity) -> bool { + match self { + AnyAddress::Address(id) => identity.address.eq(id), + AnyAddress::Short(id) => identity.address.prefix().eq(id), + } + } + + pub fn prefix(&self) -> &ShortAddress { + match self { + AnyAddress::Address(id) => id.prefix(), + AnyAddress::Short(id) => id, + } + } + /// Returns `true` if `other` contains the most complete version of the identity between + /// `self` and `other`. + /// Otherwise returns `false`. + /// This function will debug panic if `self` and `other` are not identifiers for the same peer. + /// The caller must check for equality before calling this function. + /// TODO: make this function take into account identity lifetime. + pub fn upgrade_check(&self, other: &Self) -> bool { + debug_assert_eq!(self, other); + use AnyAddress::*; + match (self, other) { + (Short(_), Address(_)) => true, + _ => false, + } + } +} +/// Does not preserve transitivity. +impl std::cmp::PartialEq for AnyAddress { + fn eq(&self, other: &Self) -> bool { + use AnyAddress::*; + match (self, other) { + (Address(addr0), Address(addr1)) => addr0.eq(addr1), + (Address(addr0), Short(addr1)) => addr0.prefix().eq(addr1), + (Short(addr0), Address(addr1)) => addr0.eq(addr1.prefix()), + (Short(addr0), Short(addr1)) => addr0.eq(addr1), + } + } +} +impl From
for AnyAddress { + fn from(value: Address) -> Self { + Self::Address(value) + } +} +impl From for AnyAddress { + fn from(value: ShortAddress) -> Self { + Self::Short(value) + } +} +impl From<&Address> for AnyAddress { + fn from(value: &Address) -> Self { + Self::Address(*value) + } +} +impl From<&ShortAddress> for AnyAddress { + fn from(value: &ShortAddress) -> Self { + Self::Short(*value) + } +} diff --git a/src/p384/identity.rs b/src/p384/identity.rs index d138d54..204c6c2 100644 --- a/src/p384/identity.rs +++ b/src/p384/identity.rs @@ -1,3 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ + */ use crate::p384::*; const TIMESTAMP_START: usize = P384_PUBLIC_KEY_SIZE; diff --git a/src/p384/identity_secret.rs b/src/p384/identity_secret.rs index 876acdf..870d542 100644 --- a/src/p384/identity_secret.rs +++ b/src/p384/identity_secret.rs @@ -1,3 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ + */ use crate::p384::*; /// Secret NIST P-384 identity (also contains public). diff --git a/src/p384/mod.rs b/src/p384/mod.rs index 542638a..971cd7c 100644 --- a/src/p384/mod.rs +++ b/src/p384/mod.rs @@ -5,7 +5,6 @@ * (c) ZeroTier, Inc. * https://www.zerotier.com/ */ - use std::fmt::Debug; use std::hash::Hash; use std::io::Write; @@ -18,15 +17,17 @@ use crate::zeroize::{Zeroize, ZeroizeOnDrop}; use zerotier_common_utils::{base64, blob::Blob, error::InvalidParameterError, tofrombytes::ToFromBytes}; use zerotier_crypto_glue::{hash::SHA384, p384::*}; -use crate::base24; +use crate::{base24, base62}; use crate::{ADDRESS_ERR, IDENTITY_ERR}; mod address; +mod identifier; mod identity; mod identity_secret; mod short_address; pub use address::*; +pub use identifier::*; pub use identity::*; pub use identity_secret::*; pub use short_address::*; diff --git a/src/p384/short_address.rs b/src/p384/short_address.rs index 387f7bc..c1a00fb 100644 --- a/src/p384/short_address.rs +++ b/src/p384/short_address.rs @@ -1,3 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ + */ use crate::p384::*; /// 128-bit short address prefix.