mirror of
https://github.com/zerotier/identity.git
synced 2026-05-22 16:29:03 -07:00
Add MPL and more tests, fix base62.
This commit is contained in:
+19
-3
@@ -29,14 +29,30 @@ pub fn decode_11to8(s: &[u8]) -> Result<u64, InvalidParameterError> {
|
||||
let c = *c;
|
||||
n *= 62;
|
||||
n = n.wrapping_add(if c >= 97 && c <= 122 {
|
||||
n - 97
|
||||
c - 97
|
||||
} else if c >= 65 && c <= 90 {
|
||||
n - 39
|
||||
c - 39
|
||||
} else if c >= 48 && c <= 57 {
|
||||
n + 4
|
||||
c + 4
|
||||
} else {
|
||||
return Err(InvalidParameterError("invalid base62"));
|
||||
} as u64);
|
||||
}
|
||||
return Ok(n);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
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();
|
||||
tmp.clear();
|
||||
encode_8to11(r, &mut tmp);
|
||||
assert_eq!(decode_11to8(tmp.as_bytes()).unwrap(), r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+23
-13
@@ -1,3 +1,11 @@
|
||||
/* 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 std::hash::Hash;
|
||||
use std::io::Write;
|
||||
use std::mem::{size_of, transmute};
|
||||
@@ -30,21 +38,23 @@ impl Address {
|
||||
/// These addresses have the prefix 0xfc so their 128-bit short prefix is also a private IPv6 address.
|
||||
pub const REQUIRED_PREFIX: u8 = 0xfc;
|
||||
|
||||
/// Length of a full address in string format.
|
||||
pub const STRING_SIZE: usize = 76;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn as_bytes(&self) -> &[u8; 48] {
|
||||
debug_assert_eq!(size_of::<[u8; 48]>(), size_of::<[u64; 6]>());
|
||||
debug_assert_eq!(size_of::<[u8; 48]>(), size_of::<Self>());
|
||||
unsafe { &*self.0.as_ptr().cast::<[u8; 48]>() }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn prefix(&self) -> &ShortAddress {
|
||||
// Safe since this is a transparent u128.
|
||||
unsafe { transmute(&self.0[0]) }
|
||||
unsafe { transmute(&self.0) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn as_mut_bytes(&mut self) -> &mut [u8; 48] {
|
||||
debug_assert_eq!(size_of::<[u8; 48]>(), size_of::<[u64; 6]>());
|
||||
debug_assert_eq!(size_of::<[u8; 48]>(), size_of::<Self>());
|
||||
unsafe { &mut *self.0.as_mut_ptr().cast::<[u8; 48]>() }
|
||||
}
|
||||
|
||||
@@ -57,13 +67,13 @@ impl Address {
|
||||
impl ShortAddress {
|
||||
#[inline(always)]
|
||||
pub fn as_bytes(&self) -> &[u8; 16] {
|
||||
debug_assert_eq!(size_of::<[u8; 16]>(), size_of::<[u64; 2]>());
|
||||
debug_assert_eq!(size_of::<[u8; 16]>(), size_of::<Self>());
|
||||
unsafe { &*(&self.0 as *const [u64; 2]).cast() }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn as_mut_bytes(&mut self) -> &mut [u8; 16] {
|
||||
debug_assert_eq!(size_of::<[u8; 16]>(), size_of::<[u64; 2]>());
|
||||
debug_assert_eq!(size_of::<[u8; 16]>(), size_of::<Self>());
|
||||
unsafe { &mut *(&mut self.0 as *mut [u64; 2]).cast() }
|
||||
}
|
||||
|
||||
@@ -127,7 +137,7 @@ fn first_128_to_string(b: &[u8], s: &mut String) {
|
||||
|
||||
impl ToString for Address {
|
||||
fn to_string(&self) -> String {
|
||||
let mut s = String::with_capacity(76);
|
||||
let mut s = String::with_capacity(Self::STRING_SIZE);
|
||||
first_128_to_string(&self.as_bytes()[..16], &mut s);
|
||||
s.push('.');
|
||||
base62::encode_8to11(u64::from_be(self.0[2]), &mut s);
|
||||
@@ -152,15 +162,15 @@ impl FromStr for Address {
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.trim();
|
||||
let sb = s.as_bytes();
|
||||
if s.len() == sb.len() && sb.len() == 76 && sb[32] == b'.' {
|
||||
if s.len() == sb.len() && sb.len() == Self::STRING_SIZE && sb[31] == b'.' {
|
||||
let prefix = ShortAddress::from_str(&s[..32])?;
|
||||
Ok(Address([
|
||||
prefix.0[0],
|
||||
prefix.0[1],
|
||||
base62::decode_11to8(&sb[33..44])?.to_be(),
|
||||
base62::decode_11to8(&sb[44..55])?.to_be(),
|
||||
base62::decode_11to8(&sb[55..66])?.to_be(),
|
||||
base62::decode_11to8(&sb[66..77])?.to_be(),
|
||||
base62::decode_11to8(&sb[32..43])?.to_be(),
|
||||
base62::decode_11to8(&sb[43..54])?.to_be(),
|
||||
base62::decode_11to8(&sb[54..65])?.to_be(),
|
||||
base62::decode_11to8(&sb[65..76])?.to_be(),
|
||||
]))
|
||||
} else {
|
||||
Err(ADDRESS_ERR)
|
||||
@@ -643,6 +653,6 @@ mod tests {
|
||||
println!("P: {}", secret.public.to_string());
|
||||
}
|
||||
let end = ms_monotonic();
|
||||
println!("generation time: {} ms/identity", ((end - start) as f64) / 3.0);
|
||||
println!("p384 generation time: {} ms/identity", ((end - start) as f64) / 3.0);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1
@@ -1,3 +1,11 @@
|
||||
/* 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 std::alloc::{alloc, Layout};
|
||||
use std::hash::Hash;
|
||||
use std::mem::transmute_copy;
|
||||
@@ -497,7 +505,7 @@ mod tests {
|
||||
println!("P: {}", secret.public.to_string());
|
||||
}
|
||||
let end = ms_monotonic();
|
||||
println!("generation time: {} ms/identity", ((end - start) as f64) / 3.0);
|
||||
println!("x25519 generation time: {} ms/identity", ((end - start) as f64) / 3.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user