Implement a hybrid key, rev identity again to make it upgradable.

This commit is contained in:
Adam Ierymenko 2022-02-18 12:03:45 -05:00
parent a60e4838fe
commit d5be872491
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
6 changed files with 271 additions and 87 deletions

View file

@ -240,9 +240,23 @@ pub fn hmac_sha512(key: &[u8], msg: &[u8]) -> [u8; 64] {
hm.finish()
}
#[inline(always)]
pub fn hmac_sha512_into(key: &[u8], msg: &[u8], md: &mut [u8]) {
let mut hm = HMACSHA512::new(key);
hm.update(msg);
hm.finish_into(md);
}
#[inline(always)]
pub fn hmac_sha384(key: &[u8], msg: &[u8]) -> [u8; 48] {
let mut hm = HMACSHA384::new(key);
hm.update(msg);
hm.finish()
}
#[inline(always)]
pub fn hmac_sha384_into(key: &[u8], msg: &[u8], md: &mut [u8]) {
let mut hm = HMACSHA384::new(key);
hm.update(msg);
hm.finish_into(md);
}

View file

@ -6,8 +6,8 @@
* https://www.zerotier.com/
*/
pub mod pool;
pub mod gate;
pub(crate) mod pool;
pub(crate) mod gate;
pub mod buffer;
pub use zerotier_core_crypto::hex;

View file

@ -0,0 +1,137 @@
/* 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)2021 ZeroTier, Inc.
* https://www.zerotier.com/
*/
use std::io::Write;
use zerotier_core_crypto::c25519::{C25519_PUBLIC_KEY_SIZE, C25519KeyPair};
use zerotier_core_crypto::hash::{hmac_sha512, SHA512};
use zerotier_core_crypto::p384::{P384_PUBLIC_KEY_SIZE, P384KeyPair, P384PublicKey};
use zerotier_core_crypto::secret::Secret;
pub const ALGORITHM_C25519: u8 = 0x01;
pub const ALGORITHM_ECC_NIST_P384: u8 = 0x02;
/// A bundle of key pairs for multiple algorithms that can be used to execute key agreement.
///
/// These are used in ephemeral session key negotiation.
#[derive(Clone)]
pub struct HybridKeyPair {
pub c25519: C25519KeyPair,
pub p384: P384KeyPair
}
impl HybridKeyPair {
#[inline(always)]
pub fn generate() -> HybridKeyPair {
Self {
c25519: C25519KeyPair::generate(),
p384: P384KeyPair::generate()
}
}
#[inline(always)]
pub fn get_public(&self) -> HybridPublicKey {
HybridPublicKey {
c25519: Some(self.c25519.public_bytes().clone()),
p384: Some(self.p384.public_key().clone())
}
}
/// Execute key agreement using all keys in common between this and the other public key.
///
/// If there are FIPS/NIST approved keys present these will be used last in a chain of
/// HMAC(previous, next) KDF operations, making the final result FIPS-compliant. Non-FIPS
/// algorithms before it can be considered "salts" input to HKDF for FIPS purposes.
pub fn agree(&self, other_public: &HybridPublicKey) -> Option<Secret<64>> {
let mut k: Option<Secret<64>> = None;
if other_public.c25519.is_some() {
// k can't have anything in it yet since this is the first checked
let _ = k.insert(Secret(SHA512::hash(self.c25519.agree(other_public.c25519.as_ref().unwrap()).as_bytes())));
}
if other_public.p384.is_some() {
let p384_secret = self.p384.agree(other_public.p384.as_ref().unwrap());
if p384_secret.is_none() {
return None;
}
if k.is_some() {
let prev_k = k.take().unwrap();
let _ = k.insert(Secret(hmac_sha512(prev_k.as_bytes(), p384_secret.unwrap().as_bytes())));
} else {
let _ = k.insert(Secret(SHA512::hash(p384_secret.unwrap().as_bytes())));
}
}
return k;
}
}
unsafe impl Send for HybridKeyPair {}
unsafe impl Sync for HybridKeyPair {}
/// A public key composed of multiple public keys for multiple algorithms.
///
/// The key pair above currently always uses every algorithm but the protocol permits
/// mix-and-match. At least one must be present though or agreement will fail.
#[derive(Clone)]
pub struct HybridPublicKey {
pub c25519: Option<[u8; C25519_PUBLIC_KEY_SIZE]>,
pub p384: Option<P384PublicKey>
}
impl HybridPublicKey {
pub fn from_bytes(mut b: &[u8]) -> Option<HybridPublicKey> {
if !b.is_empty() {
let mut hpk = Self { c25519: None, p384: None };
let types = b[0];
b = &b[1..];
let mut have = false;
if (types & ALGORITHM_C25519) != 0 {
if b.len() < C25519_PUBLIC_KEY_SIZE {
return None;
}
let _ = hpk.c25519.insert((&b[0..C25519_PUBLIC_KEY_SIZE]).try_into().unwrap());
b = &b[C25519_PUBLIC_KEY_SIZE..];
have = true;
}
if (types & ALGORITHM_ECC_NIST_P384) != 0 {
if b.len() < P384_PUBLIC_KEY_SIZE {
return None;
}
let pk = P384PublicKey::from_bytes(&b[0..P384_PUBLIC_KEY_SIZE]);
if pk.is_none() {
return None;
}
let _ = hpk.p384.insert(pk.unwrap());
b = &b[P384_PUBLIC_KEY_SIZE..];
have = true;
}
if have {
return Some(hpk);
}
}
return None;
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut buf: Vec<u8> = Vec::with_capacity(1 + C25519_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE);
buf.push(0);
if self.c25519.is_some() {
*buf.get_mut(0).unwrap() |= ALGORITHM_C25519;
let _ = buf.write_all(self.c25519.as_ref().unwrap());
}
if self.p384.is_some() {
*buf.get_mut(0).unwrap() |= ALGORITHM_ECC_NIST_P384;
let _ = buf.write_all(self.p384.as_ref().unwrap().as_bytes());
}
buf
}
}
unsafe impl Send for HybridPublicKey {}
unsafe impl Sync for HybridPublicKey {}

View file

@ -24,11 +24,11 @@ use zerotier_core_crypto::p384::*;
use zerotier_core_crypto::salsa::Salsa;
use zerotier_core_crypto::secret::Secret;
use crate::error::InvalidFormatError;
use crate::error::{InvalidFormatError, InvalidParameterError};
use crate::util::buffer::Buffer;
use crate::util::pool::{Pool, Pooled, PoolFactory};
use crate::vl1::Address;
use crate::vl1::protocol::{ADDRESS_SIZE, ADDRESS_SIZE_STRING, IDENTITY_V0_POW_THRESHOLD, IDENTITY_V1_POW_THRESHOLD};
use crate::vl1::protocol::{ADDRESS_SIZE, ADDRESS_SIZE_STRING, IDENTITY_POW_THRESHOLD};
/// Curve25519 and Ed25519
pub const IDENTITY_ALGORITHM_X25519: u8 = 0x01;
@ -112,7 +112,7 @@ impl Identity {
let mut digest = sha.finish();
zt_address_derivation_memory_intensive_hash(&mut digest, &mut genmem_pool_obj);
if digest[0] < IDENTITY_V1_POW_THRESHOLD {
if digest[0] < IDENTITY_POW_THRESHOLD {
let addr = Address::from_bytes(&digest[59..64]);
if addr.is_some() {
address = addr.unwrap();
@ -124,45 +124,70 @@ impl Identity {
}
drop(genmem_pool_obj);
let mut id = Self {
address,
c25519: c25519_pub,
ed25519: ed25519_pub,
p384: None,
secret: Some(IdentitySecret {
c25519,
ed25519,
p384: None,
}),
fingerprint: [0_u8; 64] // replaced in upgrade()
};
assert!(id.upgrade().is_ok());
id
}
/// Upgrade older x25519-only identities to hybrid identities with both x25519 and NIST P-384 curves.
///
/// The identity must contain its x25519 secret key or an error occurs. If the identity is already
/// a new form hybrid identity nothing happens and Ok is returned.
pub fn upgrade(&mut self) -> Result<(), InvalidParameterError> {
if self.secret.is_none() {
return Err(InvalidParameterError("an identity can only be upgraded if it includes its private key"));
}
if self.p384.is_none() {
let p384_ecdh = P384KeyPair::generate();
let p384_ecdsa = P384KeyPair::generate();
let mut self_sign_buf: Vec<u8> = Vec::with_capacity(ADDRESS_SIZE + 4 + C25519_PUBLIC_KEY_SIZE + ED25519_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE);
let _ = self_sign_buf.write_all(&address.to_bytes());
let _ = self_sign_buf.write_all(&c25519_pub);
let _ = self_sign_buf.write_all(&ed25519_pub);
let mut self_sign_buf: Vec<u8> = Vec::with_capacity(ADDRESS_SIZE + C25519_PUBLIC_KEY_SIZE + ED25519_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_ECDSA_SIGNATURE_SIZE + 4);
let _ = self_sign_buf.write_all(&self.address.to_bytes());
let _ = self_sign_buf.write_all(&self.c25519);
let _ = self_sign_buf.write_all(&self.ed25519);
self_sign_buf.push(IDENTITY_ALGORITHM_EC_NIST_P384);
let _ = self_sign_buf.write_all(p384_ecdh.public_key_bytes());
let _ = self_sign_buf.write_all(p384_ecdsa.public_key_bytes());
// Sign all keys including the x25519 ones with the new P-384 keys.
let ecdsa_self_signature = p384_ecdsa.sign(self_sign_buf.as_slice());
let ed25519_self_signature = ed25519.sign(self_sign_buf.as_slice());
// Sign everything with the original ed25519 key to bind the new key pairs. Include the ECDSA
// signature because these signatures are not deterministic. We don't want the ability to
// make a new identity with the same address but a different fingerprint by mangling the
// ECDSA signature in some way.
let _ = self_sign_buf.write_all(&ecdsa_self_signature);
let ed25519_self_signature = self.secret.as_ref().unwrap().ed25519.sign(self_sign_buf.as_slice());
let mut sha = SHA512::new();
sha.update(self_sign_buf.as_slice());
sha.update(&ecdsa_self_signature);
sha.update(&ed25519_self_signature);
Self {
address,
c25519: c25519_pub,
ed25519: ed25519_pub,
p384: Some(IdentityP384Public {
let _ = self.p384.insert(IdentityP384Public {
ecdh: p384_ecdh.public_key().clone(),
ecdsa: p384_ecdsa.public_key().clone(),
ecdsa_self_signature,
ed25519_self_signature,
}),
secret: Some(IdentitySecret {
c25519,
ed25519,
p384: Some(IdentityP384Secret {
});
let _ = self.secret.as_mut().unwrap().p384.insert(IdentityP384Secret {
ecdh: p384_ecdh,
ecdsa: p384_ecdsa,
}),
}),
fingerprint: sha.finish()
});
self.fingerprint = sha.finish();
}
return Ok(());
}
#[inline(always)]
@ -174,28 +199,11 @@ impl Identity {
}
}
/// Get a SHA384 hash of this identity's address and public keys.
/// This is a SHA384 counterpart to the sha512 field.
pub fn sha384(&self) -> [u8; SHA384_HASH_SIZE] {
let mut sha = SHA384::new();
sha.update(&self.address.to_bytes());
sha.update(&self.c25519);
sha.update(&self.ed25519);
let _ = self.p384.as_ref().map(|p384| {
sha.update(&[IDENTITY_ALGORITHM_EC_NIST_P384]);
sha.update(p384.ecdh.as_bytes());
sha.update(p384.ecdsa.as_bytes());
sha.update(&p384.ecdsa_self_signature);
sha.update(&p384.ed25519_self_signature);
});
sha.finish()
}
/// Locally check the validity of this identity.
///
/// This is somewhat time consuming due to the memory-intensive work algorithm.
pub fn validate_identity(&self) -> bool {
let pow_threshold = if self.p384.is_some() {
if self.p384.is_some() {
let p384 = self.p384.as_ref().unwrap();
let mut self_sign_buf: Vec<u8> = Vec::with_capacity(ADDRESS_SIZE + 4 + C25519_PUBLIC_KEY_SIZE + ED25519_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE);
@ -207,16 +215,18 @@ impl Identity {
let _ = self_sign_buf.write_all(p384.ecdsa.as_bytes());
if !p384.ecdsa.verify(self_sign_buf.as_slice(), &p384.ecdsa_self_signature) {
return false;
}
if !ed25519_verify(&self.ed25519, &p384.ed25519_self_signature, self_sign_buf.as_slice()) {
println!("foo");
return false;
}
IDENTITY_V1_POW_THRESHOLD
} else {
IDENTITY_V0_POW_THRESHOLD
};
let _ = self_sign_buf.write_all(&p384.ecdsa_self_signature);
if !ed25519_verify(&self.ed25519, &p384.ed25519_self_signature, self_sign_buf.as_slice()) {
println!("bar");
return false;
}
}
// NOTE: fingerprint is always computed locally, so no need to check it.
let mut sha = SHA512::new();
sha.update(&self.c25519);
@ -226,7 +236,7 @@ impl Identity {
zt_address_derivation_memory_intensive_hash(&mut digest, &mut genmem_pool_obj);
drop(genmem_pool_obj);
return digest[0] < pow_threshold && Address::from_bytes(&digest[59..64]).map_or(false, |a| a == self.address);
return digest[0] < IDENTITY_POW_THRESHOLD && Address::from_bytes(&digest[59..64]).map_or(false, |a| a == self.address);
}
/// Perform ECDH key agreement, returning a shared secret or None on error.
@ -815,16 +825,16 @@ mod tests {
"aec623e59d:0:d7b1a715d95490611b8d467bbee442e3c88949f677371d3692da92f5b23d9e01bb916596cc1ddd2d5e0e5ecd6c750bb71ad2ba594b614b771c6f07b39dbe4126:ae4e4759d67158dcc54ede8c8ddb08acac49baf8b816883fc0ac5b6e328d17ced5f05ee0b4cd20b03bc5005471795c29206b835081b873fef26d3941416bd626%"
];
const GOOD_V1_IDENTITIES: [&'static str; 10] = [
"7c2b729f7b:0:4d9d097668f27decb7a56953cf560f595e13c48873c40c4dc19dc5a716aa551e7c0b91d00f2af1bcaa7e31f5cfe38077eb55aad97dcbb0f3b013b5297a93aa2d::2:A4Ro-uv9LK9Je7RHDOAzV_RbrG-rZ6v7_7ePKzfQk_uo0-avhSlkT8NR408L6a5cvQIDhDVhBWYR_eAaTrE888Val9FSMaM_ekmle6k74V7fi0fcA5Jhsg-eHfyw1z_ovGpWppJEs0xX5SMOCM2MBs93K20e9P4IpdFXayoLod9FAKAn-arh94tbkUALr4Uf59ACLovMymhoJr6Y-wkKRwEsnAOdSNa8bN3HGGVDOykAgvLs1E65pkIkFXTxmcSVMLbETKETYwmSaaNYEXMVGD5HBJ0GqA8298bs4HVYjNoYwMHu--Hwb1joQS0XK5WjifYRrWAA94J48f05tMDklQcF",
"0d4be14d60:0:69c300b00e5af62e2d55c1ea81f5316375038608ad3696f67bf092f960e4f7036e51a091c88c1bcadf00cf43647e9464b53017a760e24deb76f776488d430237::2:ArquLyV1f3eaXkFZPdRHzgEhD01HK0tgzXBiWO5a1flT1agj_lkyNziY-YyOoP1fEQKplNnnXhryqI75siIZFMMUZInzlJm1Ll84_qV2pfbcFMXNN--4P5LgtChR1DNNHaKLMHt5U0IKh9UwSvfH5xbTr8LjadezbPOuy9a-uf-FSQTBZvALYtLSKLjPvaNMLMamT6ruEuJbgRLsCeZ38zEqMPYQ05iG4_TrjAw0uZJ4pz8m--STLE6B5XOU3Lc50fzxdDrIqL-dDTbCX5XecQzDiN8a3CSf8vq2uMu3-Fs6AaQ_dNc8_B8Y2dpfc7UYj7sRmAyFiw0FEwHIPPSZDjsI",
"d2608c9625:0:5a19103678e8a28942d077278024421219c5dcf6e25fd8d74c082df6e288ec581ac09d4bc84b9ef2287342c1b4736da59109d9986740a9d135621399569161cc::2:A5T6RjeDlzTvJAFHlXfSFP3dOPWxCaE1jRcAdzZgxsdy80TV7pVRiAyeOdYGJEbFaQPa0qIl20ZHXUI5fZfUc7PWxp3wkQqkqD9X-3Ms3wOPP5kc_kqxKIGnlXk6E_NEggZIPr0LONZShGrDRO-kKsdDxzP9EE4FDlnrD0E2yAbjH8hAIQqhERarSabCNE_iJrJG30yi0bPZtJNI36SPJex11X8X7Vu8GFXqWmZQRIU9Q1WJBmX-LVwxxD4BzNKWsy_txeQeGokKGydV3ejASi6ViicbwxtkVHbPzDgYl0kOBwv_qJTg3PIt1x27qTAYPs4qG6PSWQt_eqGtrKCYVOAO",
"7615cd90d0:0:49641eb54b001b1c91afd162a780252bea7e315c7454beda712864e5ad801046eedb11927cdef951c64c12706cc4f332512307de9754d99ab1978b396d5c70a2::2:A-KmSE-Cga8As0AT25LxJTOLntyN1ORiJ6it_Ud6CfGPbANpvEnAbs2m7i7yJ_DP9APo4Q9RrQKS5THa0yADD_QWLz-o7zb4cTfAoG0IkVed2sWWq7SR0-6VHQWg__WglqMYIKM4FXPZ9i1uuKLrshN-fF4XAdqJLrqWTpqvpVmdYJB9LKez5MpEXO-UeLJb-4jgeFjB35Qxbcp6TsVZca3ep5FzqYdyNjfI7RkKTPnVpCKdTWFmIbDqzQMyjqg93lu8OWq2tPorzUth-qpWf9AWTPYxofNzd_t9OMimR6kevaG-qjsEX7-SOzf-UI76y3JR6lF9dMs3UiqVjv3guDgE",
"bf7544ad9f:0:fb726a8e1c8c50100661ca64a99504b13ad7d0604db1c96c35f94091aaed69168e118aa7c3ca7f4aad092a02513ca171ca5fdc445f1bbc2dda49e8af544f941b::2:A0NV5tU0HTcdrJQzjgGy01FbHzi0v7DnpkyrmNvGrcJwcU6Fas35vmpNBJpsi9YTRQPNCzPYkeMz_7s59ukEzK-Lhk5ZxyvGdJMUoW6mmWiE8T6pJcD3JC37kNRuW28cH13d5_YuDnVsPz-p1ER2d2BzvjucwgkhmQnMSWSVCNikfe7pR-2mqFjr2KkEHqCp5js1tdM-nzOrV7smjed1vl2AZIeYRBcpJXBCDiyCMSpe8MD32KcNoJPINHu6k7uDxKKEwSocacDAI8SlFjz5Sb_JXM0XUDZyoSrql9bAdDi4s4bVVjTrpOqcUfQ9Shs-QKNcrOmDG-uyM4Pqaz5NRhsF",
"e7ea5a5db4:0:1fc5c90b7350899babf0e20b3aaf7d778d63cd8b587f966e194841e80fc69a73a2c2ae340ae78b5aea47733352eddbd501147d464ef7d31297832a4a80473c40::2:Ahq6VPPeoqNX-SbAuxg2GjgxJw_4dJQb7hCL_hZ3ZZD8QHey5oK8rEg8U5GBT0M92wK4SXrUTJErbn2xxL5mFfzq4Yv_C5V_y88LYDV_pAZ5vA4HVzIs1dYXrKJZzgt9CwHev05MbvOguc3ueUGxYw5ZVR7l9RM-O4CXgvpWre8kuElv6nXfT6Rrs7UFHgJqpdti93vDMBiY6_4_sk68OFDTakqixHO0qxPwWHDOFW9OWBDCeWuDtpv3VLhCYspGKborJMbraQkkXwkd04Tm5-UgsXFfXRXP_qR4RBLmxFmf7kuSHQzqTJJQ-kIw0ZUKqvNCjqP1ii2LIa3YcXJjNZQF",
"e431ace96f:0:1a665addeb00bd8f6d46cc0cc8fa39cb3932a93e737263c431435c9f80828a7f98020ecbc6240e8284dbd2f9ddce212da5c9d8d565110e278b54a50259835c76::2:AinmOs3et5j0jzNiQj31hp8Fyb_REuhr8CdFyEZuS2uU4xu9eMo9GDUHCq_DzbyqgAK0ppN9ZaE0PTT-FLRcVBZpQ25MgPw99LMT85o7nGc0l2ffsPBiOn8s6A4U551d1glzgwBkQuUNUrO1dKHd77_ZZ0uSHybxg_eVyD-FOmXkJCc1WcFhaao7Mlso0U9XV7olrRspEs75jN3gKgnEAqp3LzpB0gX_DeTJQE9eCuJ9d72oooRqrh2VcO0Bq6K8X7IUU5q5VRzJELeedeloatyRSEzpRCiXNVweCo2J9H-in6km0SaZgk0PZIJUSB5PZOrhdvw7WQONWaigD112LtcC",
"3596edb275:0:b3a8e692955d9d2fe216e144dd91b467878d91d5d308f97b72f100b5b3f73501406f77fc00a71b7814bd4fa7b3f3e161cf55c8c50400a239a062a4b5da56f11c::2:AyDEvg6plLbzsM1pNExvF7HIeOwVSfzMpE9rqX5Bs9tOW5NNcyEb6xkYlOKIbYNTgAL2hGWLBN4pUSV9x6uDDolgtQRR84dUEmDTFynxp5lYPLo8viOqNgdrWilkx_H2hZSoStSrdecGAXIAsEbE_4NHZqA05yqiLnG_WvMxBE4s3NYVwttcVNCL2-GNQ019_cEXENeKM_0KgXY5f4WubbEL-mJzTkvjAnA8MhAbGnk3DkzdQ8syiqvgtuZGNeQ_vVyhqVJ1W7FrI-KeXB0o4dIfRQNLEue7YhSg7MPdFkaaqfe5pqHXHIbu-upYn3RNJsL7WTzjQIycW1r3v2NXlAwM",
"bb94fbb14c:0:f44e527f3776173dd8e7106f458dfb1acf680f5555d9cbe48de4daed8b3d0a4b692c3a5af67bfbfc5b275df8c6d27f2c647f529d3e1d33a0b52f5f800a5bb44e::2:Axt5NjbXaCznLoTQ6FZ2KB0WF9GSerApl94XXb3myLopi273EjLTKfzoqRe_1dhBnQOpn1RKKA27WY9WFU8vLfmxyEitLUhy8_8R86qQHwW2YIXz9OGlO4PQ2vDyzFEP28AdqQDSi3_ZbE68cTY4FdOtLYhmelvX6tzUXc6Oc0b2Fr_3DCBMVxLJwbuP2HzH-k3yGTa2jn2xBtb40jCQoS3CbQf5Pa7UW6elOmsL2KP4iupVq_FQk4fXZKXlVGjru6UAQE686KnMuzSc0TEeLG360JggmZhsxUN72xM6ei88L_BTu6srMGe3K0QLE_K1eFUXWat7WQ8Bim5G6FSMv1UD",
"91174e9989:0:d268c8b9856a8051f0794f4c221a08fb9764418187d28af7c205d89e9facc924c633af7f63cc3878bea5aefde175e16e068e93efd00f7f241c0aa7495cdd00ae::2:A5hywCOYFiGs_r347-0A9oAArsrWHwn8Zpy1AXRh4ZrVhLEH0Zzle6qek0WC3982oQMMY6ljD5DpLWwoqZwSGZDRpRIOIGutEyR-y-mvwv-nr970G7AlC7vTmCq-GGvSiDhL1S6og_JpHtGVpj6gEaTirIcG27503PhKwnZ93x8FLN-wFVX9TamePGGA82A3rkuuC90qI8bdpsAYNDZzGbXSuCSJLEaXFRj0efJn0l-No7_NnNGdBce6IYuV2jYbNxUV7AqUlhWEw8WWZl5OX9VOvskI6DGtZ13NMWc6q-1OSf8jqThdh1PeDFVNYy1qX5AI88GHQfIs54GIT8FAJeAG"
"c35be0ca60:0:bd7b7d9f59fa7bd7700d7291f394dde3bda0c7a0d0da6b1992fdb4b74d4bba7ff831999362d996b0032e94f9454e636363a9ec125185edfa9451f2cb5a47e8aa::2:AiUlMlsVUa2wLr6hSL6PWb8v4n7H-6SjBz_rMNjQVlSgoHTKdrc2pTaFlvgXXVDsxgKYj6XOCAy-kPcB6gbaAEr4HC0BaRDphLi7Q3Od2NNx1Fm3A8NDrTX6agcVCxRybxRVkJdLFE3EBkLWMAzPQ1_Qr0nvSVGZ0inAbQEQFbd0j7aDgEsik2A2pYqhvPRINiIzPBqr7kwPL7OSXF-v6oNlwFJ5NhVmleioIGekapFJkjTYF0xxMR9eOwjHArGbHtWP_yiFgXcVwV4ta-ttjnGImjCuq9AaEqhhhYsYeGhya8Pd9e9obIwbTYIS1DaCd9fXPcK6vhnLi-wEtYZ3qg0A",
"f7193a4d70:0:a796837e99841ac933c85dee615172485c87b7d9de5493c9f2fc7c5428d88833869bcdfbbf8ab0966ba3e284e131cf89b308364ed8a2af69a6986583b490cc69::2:A44ZHHXaN9bk4vssB-HuGodAbBIHmGmRmwqyD4ocUWwQWlPaQDt_y6HbNX8GmWLv5QPoMhFzuHmusOx6sAP5-2xYnUf5mpBRGTtKvW2VxG5yHNlR6olL9p2xX2okSppuYgab7X3QzTA6AiOQYCqWs-39GDA0L68q5_Vdnebfn36u3AIh0WnUlkPzkCsqF87lrgaqq_fdtE4Dz96YhvChWevDdCHhqdzjlgddk6KREpx2IPb8dQMGtwdOQZ7Kl12Ezza69PwaFsDfp47AmfsomYIB-e4kzo3G7_2me-0Zi5By9WnPtKRYHh_5HDFpjwlg9ElIjs7cyQlgz6Duc7nQHQ4E",
"780a66fd18:0:ab09057d5ffed767bf0b7a75c8d810c878758aee85e29f80ebbb80b3aefc274b22fe7fb5757dbddd0f81621a0386a9b586b50722222b8a15fc4349f0ca102dbd::2:A7CL-xo4PA8geCRMGkDa347wtlt8vsPb5ShHQs63fDzREjqPx_ghu6lDKBZSUbfRqgPkvD-dsHbx-j-Neyvp7xF-O3TsiD_OuVmYF9MCZ8e7UeCyNN9Ao6blsHiXNlE6dL5BGcOy7kmcIGEqiLnQM_SM1iggRJI3YkpYRaGuJdu7Jpc8A0XTWVzE3RccPlbu25jvagmY4u3phR9DjA3vcaY21NLDNuyBzCXQmh66WIqjbOEcIH1Tr7JjciBdhE-cmzYqFOyGxNBDCm2oXdPHHaTMljySc526LkfiMcJilNiVrTf0-6CjccLxAXGlUU6VZz_DxPoVGRzPSj8kUbfvujwO",
"3961fb1d69:0:360b65017c4b690f370e9ac84a7cb1b2866978dbded70e2a8ca7c72c73b7bc3d74052cc8f51307a79fd570fad104447f524b4bdac9dadd8ebf7da3672a49739d::2:A-RabnEvl-55tTWseqP3IphwMM6dCi2PMAYnabt2yjWALVYqRV27VD4_T6P0H513SwOY27dfClgv3a-vVnw7uag8p4CBPax1q-nOuvrl62w8KzUcDS5eWyZxnvkR5iFBp3Iq4oSEDBBV1pzTZlc3aoz5Muqzt4c6X3Qh8Wcahnu2f86FL9Yl5xL9_al9Jh8PfnupO6uyvXv4jSQJaRZbQbJo0gl8WRsSZwHUTWgKbZdb3RcOxyOhJhj3dFMrTr3OrwjMAoAYuREsHkj72dOBuoZs5aMMsyjS4cjjFBDijJ4RhuzAd8n0hp1a_DV5roVOj_-sdMf0dPbDDibAV9nA_QUG",
"16c21adb85:0:8fe2f38bf5749861fabbedf7fcaee0dd79a6e6127f1e092c67ff2198b0475c771f26428438dadc3aefca1bef2e23a8cdbd1dd97f559e799e79617faa97c4da80::2:A48nTihf1f4MKVpCzyigjFNGcVeCynZTwMevsi07gfzpwTuRb1fjNmgfuyYh00X0mAMWdupKP_2rTpDd0vbcPb9aqxdUO9fqgmGHsTtudBWpjQVCueC_aITwmZhtF3ey--PV2iItyINxXeGGkXHr2EYoM5mfoZWuLhaEV0lmAk_FKZ-Mb09zfXfgNKXKCA2eQBWWBth-oHxH0vzlX86dd7D2qxsG2LY2hpn4ma2AaLHtZTKa_EsouTOxA43DlXeQxkDL3HSRjlX-ET_xae_JkPMuaMCmo0wKIOM3_6tYJkj5sKVK28gY_ziRC_27bznow9z3sJIvxVcx9MUu5nRgaakH",
"d2586ea351:0:9c7d5f25533d042564a8b1bd76f37c27e3bca494a6693d456703ba3eadc2d94d3f131fc7914e66347f9624d6f303964714e8d9f0b03bd79eb1dac137e6b8153b::2:AwwJDn3zibov2pahZy4Do714Zq2j8w3kmHpcAqBQkvEg4cVoHjkDUCOUW8HbivJdsQK5cZRTvcitNb65Gch8OfAGVfkDHYrO5eE0Ev7EXYlRqtqXaTzdwijVd3R1hxZh8FTln75Be0JMNDVQgjNH4F_WH2KLzNf8Uy44AIXYRVvC0GF0eAx3AqxpajqA9VsyT2mF0dwoeuwyre54SXu2w7cap8s4OlhW52Fv99NhE2W2inlI7gxBC_KdinIlTYepWcnHwFJnj6ZVeLYRMZuNGDMSUPXk00wqbqfEYdWSLGvz9g9NvSAq_NGI-L7WQCB368K1teXsdL1WLzYaA2vQYYMG",
"6ae70ee955:0:858884d8b8d863ee0fd79cd55d96034a7e1a4828f1661d362d6b2ac1e942c459a38a17907fdd268e19e82ade375a9a654e2a477a28ecaf8ce5f14c9b141d59f6::2:A0aVghbPjh5okma0NrfrArePpgX9RYj7ULLiib_DB6yh0pKYemgYY5sHmHeRrf33ngO8dYzDTSPMd_pWdGWkpiwgrCxyY8TNYxjn_b-odGxdjP9Id-QUJ9bHEAA0W1C7I3LkrWGsGajw18lUJroE4_QiwQm6Csh7l4hUma7mgyBtOumMfEdQL5sxvvv5e1E5skveuEEyCzei7tu9Yl1oFh-kqj4OAIA9fw8yc7F19a102HoGA3on_mYyEglTmoRAL7GyN8RAEGm7dzLNrwI3Q4acHFcoyA3D_pbF0EyGFN2YDTZYs7fNGP8HFXj_c_5zAmIe-99UgqlOoVAoQvQ4w8QL",
"875b7f95a6:0:0a81b6da6cc1d7924a18c3b719b1621bd9e09e0638ab86a99e530f67267c7a0fb3bcdebf09c242ff1b29f19b1442e907b06a2a81028add0090f8061c8b841636::2:AkAXRtMOLsm2LoxZ314SC9fgCOpkLwor6Mr9newu1wFJbnBNA2RVH639hRo26VDDmwJLrEH2Dxo4ssRGM4McOcRCzWi2VameTu_PqUTfZ8_B60xOfNqlES6ZS12ujho28l8kP7TFbfwl9CbB1y8Lrs5x-LbEZG0sx0PgiadcNJzjlecwcLCq7hZ58mnrKNX3clMnb59X1AVMHYsY4XlflYzkICxB_QnpNmPTyeruIg-Hl4gmnuOyYeSnEOkPTYYByxlLmc4Eyz3AqhzA634WaAfqkF1DiR4XJ3B5W1-D3Z5znIowVgNoBlIJ2uVDbjm02eRh-Glxvgt0OimuptT_GgcN",
"e4f8e758c6:0:cf3504c7392b1e15dc11a73ca76f1144578459ee32f3f12dc35bc28be93ada2cc3f8dd2ee066a9b9358a4e7653222b399b4ff2f53ecf7d264d528f8bfb3434c8::2:Aw170fJF8sqymG1z5w4K1ZSU2M2epkkXtbnnzVd9zcLEcum7CQ4_1QTZH5ze1OXzBAIOxZSy4eQBgBaNKPM2x2fGIc5eIcHgnYkXvR41hUVAhdAe4zAi52GQvyCyZ2H5qSZYZrgcHQec4ctpqZEodbfJaznO4VjOTxh6dh41SQLqjWIQmruFDSZ1KG_yQD4mRnPsMzFT4pNmIuQq-mw52_64A7RQ0wEIXRpTkfGav1if1qnfU-TQVj6I8607XugdGE3CoILRBdNMld8J3W7Cq6xHtyw6DeCPCwGN7xt4giyMsIKgbOd0x8HNHX0QRYmvmUZpPQT_wp2LA4NNieNZ9VsO",
"a6b56f96ad:0:d1d5b9cc259804516edb11903784ee3c3e69fe1b4334129a2db3859406298a3379a2fe894ce24f565fd7e2c065cdf295a7488a5197e62a9aae7d48c311d03ef7::2:AnwaTJ3eJdMKY17HlwVNKpMb_H_kezrgKYCdz_h62-eFW8DGPuqND_QRt4XDSmPO9ANZHkINJ35q4g-MfKITocXzBE3uFTgVgCJhqrsKdf2CspjQT2ZGT5xZHbKGUU9eUShpSdQEVEfuAURTOEyWzifjp9ZEqXbigWeNXaAwiUBihRvh0vMPDumvdrovxX2rAm5N1f2nKKYUYhx5YsSyBhoIjjsKei00iPoBj5gNeINylnxf6PqVyUp9HVApsupHm5xblPWhw0lwa56q5R8rKVwygtHb74qNNmFPKjS6VziNI0XxcKN9lapfj1dmmj6cXCkvdD8YpznaERclOZotdbcA"
];
#[test]
@ -846,29 +856,54 @@ mod tests {
assert!(gen2.agree(&gen).unwrap().eq(&gen.agree(&gen2).unwrap()));
for id_str in GOOD_V0_IDENTITIES {
let id = Identity::from_str(id_str).unwrap();
let mut id = Identity::from_str(id_str).unwrap();
assert!(id.validate_identity());
assert!(id.p384.is_none());
let idb = id.to_bytes(IDENTITY_ALGORITHM_ALL, true);
let mut cursor = 0;
let id_unmarshal = Identity::unmarshal(&idb, &mut cursor).expect("unmarshal v0 failed");
let id_unmarshal = Identity::unmarshal(&idb, &mut cursor).unwrap();
assert!(id == id_unmarshal);
assert!(id_unmarshal.secret.is_some());
let idb2 = id_unmarshal.to_bytes(IDENTITY_ALGORITHM_ALL, true);
assert!(idb == idb2);
assert!(Identity::from_str(id.to_string().as_str()).unwrap().eq(&id));
let idb2 = id_unmarshal.to_bytes(IDENTITY_ALGORITHM_ALL, false);
cursor = 0;
let id_unmarshal2 = Identity::unmarshal(&idb2, &mut cursor).unwrap();
assert!(id_unmarshal2 == id_unmarshal);
assert!(id_unmarshal2 == id);
assert!(id_unmarshal2.secret.is_none());
let ids = id.to_string();
assert!(Identity::from_str(ids.as_str()).unwrap() == id);
assert!(id.upgrade().is_ok());
assert!(id.validate_identity());
assert!(id.p384.is_some());
assert!(id.secret.as_ref().unwrap().p384.is_some());
let ids = id.to_string();
assert!(Identity::from_str(ids.as_str()).unwrap() == id);
}
for id_str in GOOD_V1_IDENTITIES {
let id = Identity::from_str(id_str).unwrap();
assert!(id.validate_identity());
assert!(id.p384.is_some());
let idb = id.to_bytes(IDENTITY_ALGORITHM_ALL, true);
let mut cursor = 0;
let id_unmarshal = Identity::unmarshal(&idb, &mut cursor).expect("unmarshal v1 failed");
let id_unmarshal = Identity::unmarshal(&idb, &mut cursor).unwrap();
assert!(id == id_unmarshal);
let idb2 = id_unmarshal.to_bytes(IDENTITY_ALGORITHM_ALL, true);
assert!(idb == idb2);
assert!(Identity::from_str(id.to_string().as_str()).unwrap().eq(&id));
cursor = 0;
let idb2 = id_unmarshal.to_bytes(IDENTITY_ALGORITHM_ALL, false);
let id_unmarshal2 = Identity::unmarshal(&idb2, &mut cursor).unwrap();
assert!(id_unmarshal2 == id_unmarshal);
assert!(id_unmarshal2 == id);
let ids = id.to_string();
assert!(Identity::from_str(ids.as_str()).unwrap() == id);
}
}
@ -881,6 +916,7 @@ mod tests {
let mut duration;
loop {
let _id = Identity::generate();
//println!("{}", _id.to_string());
end = SystemTime::now();
duration = end.duration_since(start).unwrap();
count += 1;

View file

@ -21,6 +21,7 @@ pub(crate) mod mac;
pub(crate) mod fragmentedpacket;
pub(crate) mod whoisqueue;
pub(crate) mod symmetricsecret;
pub(crate) mod hybridkey;
pub use address::Address;
pub use mac::MAC;

View file

@ -171,12 +171,8 @@ pub const WHOIS_RETRY_MAX: u16 = 3;
/// Maximum number of packets to queue up behind a WHOIS.
pub const WHOIS_MAX_WAITING_PACKETS: usize = 64;
/// Proof of work difficulty (threshold) for old v0 identities.
pub const IDENTITY_V0_POW_THRESHOLD: u8 = 17;
/// Proof of work difficulty (threshold) for new v1 identities.
/// This is lower than the V0 threshold, causing the V0 part of V1 identities to verify on old nodes.
pub const IDENTITY_V1_POW_THRESHOLD: u8 = 13;
/// Proof of work difficulty (threshold) for identity generation.
pub const IDENTITY_POW_THRESHOLD: u8 = 17;
/// Compress a packet and return true if compressed.
/// The 'dest' buffer must be empty (will panic otherwise). A return value of false indicates an error or