diff --git a/CHANGELOG.md b/CHANGELOG.md index a91410e..64e0135 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,14 +2,15 @@ This project follows [semantic versioning](http://semver.org). -### Unreleased +### v1.1.0 (2019-12-04) - [added] Exchange peer timeout and adapt keepalive accordingly - [added] Reducing published peer timeout to 5 min when NAT is detected - [added] Added more tests -- [changed] Rust version 1.41.0 +- [changed] Rust version 1.39.0 - [changed] Updated dependencies - [fixed] Fixed potential startup dependency issue +- [fixed] Fixed wrong base62 encoding ### v1.0.0 (2019-03-21) diff --git a/Cargo.lock b/Cargo.lock index e3d2efa..6a55993 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,42 +23,6 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "autocfg" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "backtrace" -version = "0.3.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base-62" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "bitflags" version = "1.2.1" @@ -131,26 +95,6 @@ name = "dtoa" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "failure" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "failure_derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "fnv" version = "1.0.6" @@ -295,33 +239,6 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num-bigint" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-integer" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-traits" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "percent-encoding" version = "1.0.1" @@ -466,11 +383,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rustc-demangle" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "serde" version = "1.0.103" @@ -544,17 +456,6 @@ dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "synstructure" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "tempfile" version = "3.1.0" @@ -639,9 +540,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "vpncloud" -version = "1.0.0" +version = "1.1.0" dependencies = [ - "base-62 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", "daemonize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -799,10 +699,6 @@ dependencies = [ "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14" "checksum attohttpc 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4da2f0d9a8eb4e0aabc162278968eaf753999aa4aed173b753f9fa8da4cb86" -"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" -"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" -"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" -"checksum base-62 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f28ebd71b3e708e895b83ec2d35c6e2ef96e34945706bf4d73826354e84f89b2" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum boxfnonce 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5988cb1d626264ac94100be357308f29ff7cbdd3b36bda27f450a4ee3f713426" "checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" @@ -814,8 +710,6 @@ dependencies = [ "checksum daemonize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70c24513e34f53b640819f0ac9f705b673fcf4006d7aab8778bee72ebfc89815" "checksum docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" -"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" -"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" @@ -835,9 +729,6 @@ dependencies = [ "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" -"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" -"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" -"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" "checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" @@ -856,7 +747,6 @@ dependencies = [ "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6747f8da1f2b1fabbee1aaa4eb8a11abf9adef0bf58a41cee45db5d59cecdfac" -"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" "checksum serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" @@ -867,7 +757,6 @@ dependencies = [ "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "032c03039aae92b350aad2e3779c352e104d919cb192ba2fabbd7b831ce4f0f6" "checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" -"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" diff --git a/Cargo.toml b/Cargo.toml index cc24f34..339ba33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vpncloud" -version = "1.0.0" +version = "1.1.0" authors = ["Dennis Schwerdel "] build = "build.rs" license = "GPL-3.0" @@ -28,7 +28,6 @@ igd = "0.9" siphasher = "0.3" daemonize = "0.4" ring = "0.16" -base-62 = "0.1" [build-dependencies] cc = "^1" diff --git a/assets/changelog.txt b/assets/changelog.txt index 9b6ae0f..4494974 100644 --- a/assets/changelog.txt +++ b/assets/changelog.txt @@ -1,3 +1,15 @@ +vpncloud (1.1.0) stable; urgency=medium + + * [added] Exchange peer timeout and adapt keepalive accordingly + * [added] Reducing published peer timeout to 5 min when NAT is detected + * [added] Added more tests + * [changed] Rust version 1.41.0 + * [changed] Updated dependencies + * [fixed] Fixed potential startup dependency issue + * [fixed] Fixed wrong base62 encoding + + -- Dennis Schwerdel Thu, 04 Dec 2019 19:01:34 +0100 + vpncloud (1.0.0) stable; urgency=medium * [added] Added ability to publish small beacons for rendezvous diff --git a/builder/Dockerfile-deb b/builder/Dockerfile-deb index 86930cc..643898b 100644 --- a/builder/Dockerfile-deb +++ b/builder/Dockerfile-deb @@ -9,7 +9,7 @@ RUN useradd -ms /bin/bash user USER user WORKDIR /home/user -ENV RUST=1.33.0 +ENV RUST=1.39.0 RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain ${RUST} diff --git a/builder/Dockerfile-rpm b/builder/Dockerfile-rpm index c94b051..c430c79 100644 --- a/builder/Dockerfile-rpm +++ b/builder/Dockerfile-rpm @@ -6,7 +6,7 @@ RUN useradd -ms /bin/bash user USER user WORKDIR /home/user -ENV RUST=1.33.0 +ENV RUST=1.39.0 RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain ${RUST} diff --git a/src/beacon.rs b/src/beacon.rs index 35730a1..48e7e25 100644 --- a/src/beacon.rs +++ b/src/beacon.rs @@ -2,7 +2,6 @@ // Copyright (C) 2019-2019 Dennis Schwerdel // This software is licensed under GPL-3 or newer (see LICENSE.md) -use base_62; use ring::digest; use std::{ @@ -21,7 +20,7 @@ use std::{ thread }; -use super::util::{Encoder, TimeSource}; +use super::util::{from_base62, to_base62, Encoder, TimeSource}; use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; @@ -90,11 +89,11 @@ impl BeaconSerializer { } fn begin(&self) -> String { - base_62::encode(&self.get_keystream(TYPE_BEGIN, 0, 0))[0..5].to_string() + to_base62(&self.get_keystream(TYPE_BEGIN, 0, 0))[0..5].to_string() } fn end(&self) -> String { - base_62::encode(&self.get_keystream(TYPE_END, 0, 0))[0..5].to_string() + to_base62(&self.get_keystream(TYPE_END, 0, 0))[0..5].to_string() } fn encrypt_data(&self, data: &mut Vec) { // Note: the 1 byte seed is only meant to protect from random changes, @@ -152,11 +151,11 @@ impl BeaconSerializer { data.extend_from_slice(&dat); } self.encrypt_data(&mut data); - base_62::encode(&data) + to_base62(&data) } fn peerlist_decode(&self, data: &str, ttl_hours: Option) -> Vec { - let mut data = base_62::decode(data).expect("Invalid input"); + let mut data = from_base62(data).expect("Invalid input"); let mut peers = Vec::new(); let mut pos = 0; if data.len() < 4 { @@ -327,13 +326,13 @@ fn encode() { let mut peers = Vec::new(); peers.push(SocketAddr::from_str("1.2.3.4:5678").unwrap()); peers.push(SocketAddr::from_str("6.6.6.6:53").unwrap()); - assert_eq!("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", ser.encode(&peers)); + assert_eq!("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", ser.encode(&peers)); peers.push(SocketAddr::from_str("[::1]:5678").unwrap()); - assert_eq!("juWwKjF5qZG7PE5imnpi5XARaXnP3UsMsGBLxM4FNFDzvjlKt1SO55LN", ser.encode(&peers)); + assert_eq!("3hRD8BKvg7jotek0FGLeYtIc1zj7jzPRyQscQAe9tCqnFJ0vyVfIxYMB", ser.encode(&peers)); let mut peers = Vec::new(); peers.push(SocketAddr::from_str("1.2.3.4:5678").unwrap()); peers.push(SocketAddr::from_str("6.6.6.6:54").unwrap()); - assert_eq!("juWwKIgSqTammVFRNoIVzLPO0BEO55LN", ser.encode(&peers)); + assert_eq!("3hRD86NwMC5dPp8bh5idzhMal4AIxYMB", ser.encode(&peers)); } #[test] @@ -343,11 +342,11 @@ fn decode() { let mut peers = Vec::new(); peers.push(SocketAddr::from_str("1.2.3.4:5678").unwrap()); peers.push(SocketAddr::from_str("6.6.6.6:53").unwrap()); - assert_eq!(format!("{:?}", peers), format!("{:?}", ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", None))); + assert_eq!(format!("{:?}", peers), format!("{:?}", ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", None))); peers.push(SocketAddr::from_str("[::1]:5678").unwrap()); assert_eq!( format!("{:?}", peers), - format!("{:?}", ser.decode("juWwKjF5qZG7PE5imnpi5XARaXnP3UsMsGBLxM4FNFDzvjlKt1SO55LN", None)) + format!("{:?}", ser.decode("3hRD8BKvg7jotek0FGLeYtIc1zj7jzPRyQscQAe9tCqnFJ0vyVfIxYMB", None)) ); } @@ -360,11 +359,11 @@ fn decode_split() { peers.push(SocketAddr::from_str("6.6.6.6:53").unwrap()); assert_eq!( format!("{:?}", peers), - format!("{:?}", ser.decode("juWwK-hj.VT:Yj bw\tJj\ntY(AZ)lM[fE]j7üIDäO55LN", None)) + format!("{:?}", ser.decode("3hRD8-5V.3h:1P 0g\t5U\nn9(ZW)no[qR]Doü7ZäIxYMB", None)) ); assert_eq!( format!("{:?}", peers), - format!("{:?}", ser.decode("j -, \nuW--wKhjVTYjbwJjtYAZlMfEj7IDO(5}5ÖÄÜ\nLN", None)) + format!("{:?}", ser.decode("3 -, \nhR--D85V3h1P0g5Un9ZWnoqRDo7ZI(x}YÖÄÜ\nMB", None)) ); } @@ -377,7 +376,7 @@ fn decode_offset() { peers.push(SocketAddr::from_str("6.6.6.6:53").unwrap()); assert_eq!( format!("{:?}", peers), - format!("{:?}", ser.decode("Hello World: juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN! End of the World", None)) + format!("{:?}", ser.decode("Hello World: 3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB! End of the World", None)) ); } @@ -390,7 +389,7 @@ fn decode_multiple() { peers.push(SocketAddr::from_str("6.6.6.6:53").unwrap()); assert_eq!( format!("{:?}", peers), - format!("{:?}", ser.decode("juWwKkBEVBp9SsDiN3BO55LN juWwKtGGPQz1gXIBd68O55LN", None)) + format!("{:?}", ser.decode("3hRD850fTOmqFffvcJEIxYMB 3hRD823uwTS47pupeONIxYMB", None)) ); } @@ -402,23 +401,23 @@ fn decode_ttl() { peers.push(SocketAddr::from_str("1.2.3.4:5678").unwrap()); peers.push(SocketAddr::from_str("6.6.6.6:53").unwrap()); MockTimeSource::set_time(2000 * 3600); - assert_eq!(2, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", None).len()); + assert_eq!(2, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", None).len()); MockTimeSource::set_time(2100 * 3600); - assert_eq!(2, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", None).len()); + assert_eq!(2, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", None).len()); MockTimeSource::set_time(2005 * 3600); - assert_eq!(2, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", None).len()); + assert_eq!(2, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", None).len()); MockTimeSource::set_time(1995 * 3600); - assert_eq!(2, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", None).len()); + assert_eq!(2, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", None).len()); MockTimeSource::set_time(2000 * 3600); - assert_eq!(2, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", Some(24)).len()); + assert_eq!(2, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", Some(24)).len()); MockTimeSource::set_time(1995 * 3600); - assert_eq!(2, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", Some(24)).len()); + assert_eq!(2, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", Some(24)).len()); MockTimeSource::set_time(2005 * 3600); - assert_eq!(2, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", Some(24)).len()); + assert_eq!(2, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", Some(24)).len()); MockTimeSource::set_time(2100 * 3600); - assert_eq!(0, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", Some(24)).len()); + assert_eq!(0, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", Some(24)).len()); MockTimeSource::set_time(1900 * 3600); - assert_eq!(0, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", Some(24)).len()); + assert_eq!(0, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", Some(24)).len()); } #[test] @@ -426,12 +425,12 @@ fn decode_invalid() { MockTimeSource::set_time(2000 * 3600); let ser = BeaconSerializer::::new(b"vpnc", b"mysecretkey"); assert_eq!(0, ser.decode("", None).len()); - assert_eq!(0, ser.decode("juWwKO55LN", None).len()); - assert_eq!(0, ser.decode("juWwK--", None).len()); - assert_eq!(0, ser.decode("--O55LN", None).len()); - assert_eq!(0, ser.decode("juWwKhjVTYjbwJjtYAZXMfEj7IDO55LN", None).len()); - assert_eq!(2, ser.decode("SGrivjuWwKhjVTYjbwJjtYAZlMfEj7IDO55LNjuWwK", None).len()); - assert_eq!(2, ser.decode("juWwKjuWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", None).len()); + assert_eq!(0, ser.decode("3hRD8IxYMB", None).len()); + assert_eq!(0, ser.decode("3hRD8--", None).len()); + assert_eq!(0, ser.decode("--IxYMB", None).len()); + assert_eq!(0, ser.decode("3hRD85V3h1P0g5Un8ZWnoqRDo7ZIxYMB", None).len()); + assert_eq!(2, ser.decode("IxYMB3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB3hRD8", None).len()); + assert_eq!(2, ser.decode("3hRD83hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMBIxYMB", None).len()); } diff --git a/src/util.rs b/src/util.rs index 5171870..7d1ad87 100644 --- a/src/util.rs +++ b/src/util.rs @@ -249,3 +249,79 @@ impl TimeSource for MockTimeSource { MOCK_TIME.with(|t| t.load(Ordering::SeqCst) as Time) } } + + +/// Helper function that multiplies the base62 data in buf[0..buflen] by 16 and adds m to it +fn base62_add_mult_16(buf: &mut [u8], mut buflen: usize, m: u8) -> usize { + let mut d: usize = m as usize; + for i in 0..buflen { + d += buf[i] as usize * 16; + buf[i] = (d % 62) as u8; + d /= 62; + } + assert!(d < 62); + if d > 0 { + buf[buflen] = d as u8; + buflen += 1; + } + buflen +} + +const BASE62: [char; 62] = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' +]; + +pub fn to_base62(data: &[u8]) -> String { + let l = data.len(); + let mut buf = vec![0; l * 2]; + let mut buflen = 0; + for b in data { + buflen = base62_add_mult_16(&mut buf, buflen, b / 16); + buflen = base62_add_mult_16(&mut buf, buflen, b % 16); + } + buf[0..buflen].reverse(); + let mut result = String::with_capacity(buflen); + for b in &buf[0..buflen] { + result.push(BASE62[*b as usize]); + } + result +} + +pub fn from_base62(data: &str) -> Result, char> { + let mut buf = Vec::with_capacity(data.len() / 2 + data.len() / 4); + for c in data.chars() { + let mut val = match c { + '0'..='9' => ((c as usize) % ('0' as usize)), + 'A'..='Z' => ((c as usize) % ('A' as usize)) + 10, + 'a'..='z' => ((c as usize) % ('a' as usize)) + 36, + _ => return Err(c) + }; + for i in 0..buf.len() { + val += buf[i] as usize * 62; + buf[i] = (val % 256) as u8; + val /= 256; + } + if val > 0 { + buf.push(val as u8); + } + } + buf.reverse(); + Ok(buf) +} + + +#[test] +fn base62() { + assert_eq!("", to_base62(&[0])); + assert_eq!("z", to_base62(&[61])); + assert_eq!("10", to_base62(&[62])); + assert_eq!("48", to_base62(&[1, 0])); + assert_eq!("1Xp7Ke", to_base62(b"Test")); + assert!(from_base62("").unwrap().is_empty()); + assert_eq!(vec![61], from_base62("z").unwrap()); + assert_eq!(vec![62], from_base62("10").unwrap()); + assert_eq!(vec![1, 0], from_base62("48").unwrap()); + assert_eq!(b"Test".to_vec(), from_base62("1Xp7Ke").unwrap()); +}