├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-BSD ├── LICENSE-MIT ├── README.md ├── appveyor.yml ├── codeowners ├── rust_sodium-sys ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-BSD ├── LICENSE-MIT ├── README.md ├── build.rs └── src │ ├── bindgen.rs │ ├── lib.rs │ └── seeded_rng.rs ├── rustfmt.toml ├── src ├── crypto │ ├── aead │ │ ├── aead_macros.rs │ │ ├── chacha20poly1305.rs │ │ ├── chacha20poly1305_ietf.rs │ │ └── mod.rs │ ├── auth │ │ ├── auth_macros.rs │ │ ├── hmacsha256.rs │ │ ├── hmacsha512.rs │ │ ├── hmacsha512256.rs │ │ └── mod.rs │ ├── box_ │ │ ├── curve25519xsalsa20poly1305.rs │ │ └── mod.rs │ ├── hash │ │ ├── hash_macros.rs │ │ ├── mod.rs │ │ ├── sha256.rs │ │ └── sha512.rs │ ├── kx │ │ ├── mod.rs │ │ └── x25519blake2b.rs │ ├── onetimeauth │ │ ├── mod.rs │ │ └── poly1305.rs │ ├── pwhash │ │ ├── mod.rs │ │ └── scryptsalsa208sha256.rs │ ├── scalarmult │ │ ├── curve25519.rs │ │ └── mod.rs │ ├── sealedbox │ │ ├── curve25519blake2bxsalsa20poly1305.rs │ │ └── mod.rs │ ├── secretbox │ │ ├── mod.rs │ │ └── xsalsa20poly1305.rs │ ├── shorthash │ │ ├── mod.rs │ │ └── siphash24.rs │ ├── sign │ │ ├── ed25519.rs │ │ └── mod.rs │ ├── stream │ │ ├── chacha20.rs │ │ ├── mod.rs │ │ ├── salsa20.rs │ │ ├── stream_macros.rs │ │ ├── xchacha20.rs │ │ └── xsalsa20.rs │ └── verify.rs ├── lib.rs ├── newtype_macros.rs ├── randombytes.rs ├── test_utils.rs ├── utils.rs └── version.rs ├── systest ├── Cargo.toml ├── build.rs └── src │ └── main.rs └── testvectors ├── SHA256LongMsg.rsp ├── SHA256ShortMsg.rsp ├── SHA512LongMsg.rsp ├── SHA512ShortMsg.rsp └── ed25519.input /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.sw* 3 | *.o 4 | *.so 5 | /doc 6 | .rust 7 | Cargo.lock 8 | /target 9 | rust_sodium-sys/target 10 | systest/target 11 | 12 | # Generated by Editors 13 | *~ 14 | ~* 15 | *.swp 16 | *.sublime-* 17 | *.bk 18 | 19 | # Manual 20 | .cargo/ 21 | 22 | # Misc 23 | packages/ 24 | .DS_Store 25 | *.bootstrap.cache 26 | cargo-all.sh 27 | bindings 28 | tmp 29 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | env: 2 | global: 3 | - PATH=$PATH:$HOME/.cargo/bin 4 | - RUST_BACKTRACE=1 5 | os: 6 | - linux 7 | - osx 8 | language: rust 9 | rust: 10 | - stable 11 | sudo: false 12 | branches: 13 | only: 14 | - master 15 | cache: 16 | cargo: true 17 | before_script: 18 | - curl -sSL https://github.com/maidsafe/QA/raw/master/travis/cargo_install.sh > cargo_install.sh 19 | - bash cargo_install.sh cargo-prune; 20 | - rustup component add rustfmt clippy 21 | script: 22 | - set -x; 23 | cargo fmt -- --check && 24 | cd rust_sodium-sys && cargo fmt -- --check && cd .. && 25 | cargo test --release --verbose && 26 | cargo test --release --verbose --manifest-path rust_sodium-sys/Cargo.toml && 27 | cargo clippy --all-targets && 28 | cargo clippy --manifest-path=rust_sodium-sys/Cargo.toml --all-targets 29 | before_cache: 30 | - cargo prune 31 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # rust_sodium - Change Log 2 | 3 | ## [0.10.1] 4 | - upgrade rust_sodium-sys to 0.10.3 5 | - use stable rust, 2018 edition without being tied to 6 | a specific version 7 | - use cargo fmt and cargo clippy 8 | 9 | ## [0.10.1] 10 | - upgrade rust_sodium-sys to 0.10.1 11 | - use rust to 1.29.0 stable, drop nightly 12 | - use cargo fmt and cargo clippy 13 | 14 | ## [0.10.0] 15 | - upgrade rust_sodium-sys to 0.10.0 16 | - upgrade unwrap version to 1.2.0 17 | - use rust 1.28.0 stable / 2018-07-07 nightly 18 | - rustfmt 0.99.2 and clippy-0.0.212 19 | 20 | ## [0.9.0] 21 | - upgrade libsodium version to 1.0.16 22 | - replace 'use-installed-libsodium' feature with env var 23 | - drop support for rustc-serialize since it has been deprecated 24 | - pull most outstanding sodiumoxide commits downstream 25 | - initialise libsodium in all tests 26 | - use rust 1.25.0 stable 27 | 28 | ## [0.8.0] 29 | - Use rust 1.24.0 stable / 2018-02-05 nightly 30 | - rustfmt 0.9.0 and clippy-0.0.186 31 | 32 | ## [0.7.0] 33 | - Use rust 1.22.1 stable / 2017-11-23 nightly 34 | - rustfmt 0.9.0 and clippy-0.0.174 35 | 36 | ## [0.6.0] 37 | - Add support for iOS build targets 38 | 39 | ## [0.5.0] 40 | - Use rust 1.19 stable / 2017-07-20 nightly 41 | - rustfmt 0.9.0 and clippy-0.0.144 42 | - Replace -Zno-trans with cargo check 43 | - Make appveyor script using fixed version of stable 44 | 45 | ## [0.4.0] 46 | - Changed build script for non-Windows platforms to only pass `--disable-pie` when a new env var is set. 47 | 48 | ## [0.3.0] 49 | - Ported several updates from sodiumoxide 50 | - Upgraded libsodium version to 1.0.12 51 | - Changed the default feature behaviour for rust_sodium-sys to download and unpack/build libsodium 52 | - For Linux distros, only enable PIE for Ubuntu >= 15.04 53 | - Added support for MSVC builds 54 | - Changed to use rust 1.17 stable 55 | - Updated CI script to run cargo_install from QA 56 | 57 | ## [0.2.0] 58 | - Default to serde instead of rustc-serialize 59 | - rustfmt 0.8.1 60 | - enforce min powershell major version of 4 for compilation on Windows 61 | 62 | ## [0.1.2] 63 | - Fix Windows build scripts by using curl. 64 | - Fix ARM build by allowing the `trivial_casts` lint. 65 | - Print build commands on failure. 66 | - [Upstream pull - Make vector manipulation more efficient.](https://github.com/dnaq/sodiumoxide/commit/f509c90de1a5825abf67e1d8cd8cd70a35b91880) 67 | - Added `init()` to every test. 68 | - Updated dependencies. 69 | - Added standard MaidSafe lint checks and fixed resulting warnings. 70 | 71 | ## [0.1.1] 72 | - Bugfix for missed renaming of feature gate. 73 | 74 | ## [0.1.0] 75 | - Initial fork from sodiumoxide including changes to build script. 76 | - Added `init_with_rng()` to allow sodiumoxide_extras crate to be deprecated. 77 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["MaidSafe Developers "] 3 | categories = ["cryptography"] 4 | description = "Fast cryptographic library for Rust (bindings to libsodium)" 5 | edition = "2018" 6 | homepage = "https://maidsafe.net" 7 | keywords = ["crypto", "cryptographic", "cryptography", "sodium"] 8 | license = "MIT OR BSD-3-Clause" 9 | name = "rust_sodium" 10 | readme = "README.md" 11 | repository = "https://github.com/maidsafe/rust_sodium" 12 | version = "0.10.2" 13 | 14 | [dependencies] 15 | libc = "~0.2.40" 16 | rand = "~0.4.2" 17 | rust_sodium-sys = { path = "rust_sodium-sys", version = "~0.10.3" } 18 | serde = "~1.0.37" 19 | unwrap = "~1.2.0" 20 | 21 | [dev-dependencies] 22 | hex = "~0.3.1" 23 | rmp-serde = "~0.13.7" 24 | serde_json = "~1.0.13" 25 | 26 | [features] 27 | benchmarks = [] 28 | -------------------------------------------------------------------------------- /LICENSE-BSD: -------------------------------------------------------------------------------- 1 | Copyright 2018 MaidSafe.net limited. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | 3. Neither the name of copyright holder nor the 14 | names of its contributors may be used to endorse or promote products 15 | derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright for portions of rust_sodium are held by The 2 | sodiumoxide Developers, 2015 as part of sodiumoxide. All 3 | other copyright for rust_sodium are held by 4 | MaidSafe.net limited, 2016. 5 | 6 | Permission is hereby granted, free of charge, to any 7 | person obtaining a copy of this software and associated 8 | documentation files (the "Software"), to deal in the 9 | Software without restriction, including without 10 | limitation the rights to use, copy, modify, merge, 11 | publish, distribute, sublicense, and/or sell copies of 12 | the Software, and to permit persons to whom the Software 13 | is furnished to do so, subject to the following 14 | conditions: 15 | 16 | The above copyright notice and this permission notice 17 | shall be included in all copies or substantial portions 18 | of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 21 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 22 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 23 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 24 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 27 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 | DEALINGS IN THE SOFTWARE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rust_sodium 2 | 3 | Rust bindings to [libsodium](https://github.com/jedisct1/libsodium). 4 | 5 | ## This repository has been copied to the open-development platform Subspace, you can access it directly by following [this link](https://app.dev.subspace.net/gitlab/subspace-open-development/rust_sodium). 6 | 7 | ## To learn more about Subspace, click [here](https://docs.subspace.net/). 8 | 9 | ## The rust_sodium crate is no longer maintained by MaidSafe, you should check whether it is actively maintained on Subspace as per the link above, or switch to a modern alternative. 10 | 11 | ## Interested in taking ownership? Contact us at qa@maidsafe.net 12 | 13 | 14 | 15 | This project is largely based on [sodiumoxide](https://github.com/dnaq/sodiumoxide). Some main 16 | differences are: 17 | 18 | * this project builds or downloads libsodium by default, favouring a statically-built, fixed version 19 | of the native library 20 | * offers the ability to initialise libsodium with a psuedorandom number generator, allowing for 21 | reproducible data to be generated, which can be useful in the context of tests 22 | * implements a test to ensure the FFI bindings match the native library's interface 23 | * runs CI tests on Windows (AppVeyor), OS X and Linux (Travis) 24 | 25 | |Crate|Documentation|Linux/macOS|Windows|Issues| 26 | |:---:|:-----------:|:--------:|:-----:|:----:| 27 | |[![](http://meritbadge.herokuapp.com/rust_sodium)](https://crates.io/crates/rust_sodium)|[![Documentation](https://docs.rs/rust_sodium/badge.svg)](https://docs.rs/rust_sodium)|[![Build Status](https://travis-ci.com/maidsafe/rust_sodium.svg?branch=master)](https://travis-ci.com/maidsafe/rust_sodium)|[![Build status](https://ci.appveyor.com/api/projects/status/kkgtqnx263xgk0c3/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/rust-sodium/branch/master)|[![Stories in Ready](https://badge.waffle.io/maidsafe/rust_sodium.png?label=ready&title=Ready)](https://waffle.io/maidsafe/rust_sodium)| 28 | 29 | | [MaidSafe website](https://maidsafe.net) | [SAFE Dev Forum](https://forum.safedev.org) | [SAFE Network Forum](https://safenetforum.org) | 30 | |:----------------------------------------:|:-------------------------------------------:|:----------------------------------------------:| 31 | 32 | ## Note for building on Linux 33 | 34 | Certain situations may require building libsodium configured with `--disable-pie`. To enable this, 35 | set an environment variable `RUST_SODIUM_DISABLE_PIE` while building, e.g. 36 | 37 | ```sh 38 | RUST_SODIUM_DISABLE_PIE=1 cargo build 39 | ``` 40 | 41 | ## To use your own copy of libsodium 42 | 43 | If you already have a copy of libsodium, you can choose to link this rather than having rust_sodium 44 | download and build libsodium for you. You should ensure that it is the same version as is specified 45 | in `VERSION` of 46 | [our build.rs](https://github.com/maidsafe/rust_sodium/blob/master/rust_sodium-sys/build.rs) file. 47 | 48 | Set an environment variable `RUST_SODIUM_LIB_DIR` to the folder where libsodium exists. A static 49 | version of libsodium will be preferred unless you also set `RUST_SODIUM_SHARED` to any value. 50 | 51 | Alternatively, you can use pkgconfig if appropriate to locate libsodium by setting 52 | `RUST_SODIUM_USE_PKG_CONFIG` to any value. In this case, `RUST_SODIUM_SHARED` has no effect, and 53 | generally a shared version of libsodium will be used. 54 | 55 | ## Cross-Compiling 56 | 57 | ### Cross-Compiling for ARM 58 | 59 | 1. Install dependencies and toolchain: 60 | 61 | ```sh 62 | sudo apt update 63 | sudo apt install build-essential gcc-arm-linux-gnueabihf libc6-armhf-cross libc6-dev-armhf-cross -y 64 | rustup target add armv7-unknown-linux-gnueabihf 65 | ``` 66 | 67 | 1. Add the following to a [.cargo/config file](http://doc.crates.io/config.html): 68 | 69 | ``` 70 | [target.armv7-unknown-linux-gnueabihf] 71 | linker = "arm-linux-gnueabihf-gcc" 72 | ``` 73 | 74 | 1. Build by running: 75 | 76 | ```sh 77 | cargo build --release --target armv7-unknown-linux-gnueabihf 78 | ``` 79 | 80 | ### Cross-Compiling for 32-bit Linux 81 | 82 | 1. Install dependencies and toolchain: 83 | 84 | ```sh 85 | sudo apt update 86 | sudo apt install build-essential gcc-multilib -y 87 | rustup target add i686-unknown-linux-gnu 88 | ``` 89 | 90 | 1. Build by running: 91 | 92 | ```sh 93 | cargo build --release --target i686-unknown-linux-gnu 94 | ``` 95 | 96 | ## License 97 | 98 | This SAFE Network library is dual-licensed under the Modified BSD ([LICENSE-BSD](LICENSE-BSD) https://opensource.org/licenses/BSD-3-Clause) or the MIT license ([LICENSE-MIT](LICENSE-MIT) https://opensource.org/licenses/MIT) at your option. 99 | 100 | ## Contributing 101 | 102 | Want to contribute? Great :tada: 103 | 104 | There are many ways to give back to the project, whether it be writing new code, fixing bugs, or just reporting errors. All forms of contributions are encouraged! 105 | 106 | For instructions on how to contribute, see our [Guide to contributing](https://github.com/maidsafe/QA/blob/master/CONTRIBUTING.md). 107 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | global: 3 | RUST_BACKTRACE: 1 4 | matrix: 5 | - RUST_TOOLCHAIN: stable 6 | 7 | branches: 8 | only: 9 | - master 10 | 11 | cache: 12 | - '%USERPROFILE%\.cargo' 13 | - '%APPVEYOR_BUILD_FOLDER%\target' 14 | 15 | clone_depth: 1 16 | 17 | install: 18 | - ps: | 19 | $url = "https://github.com/maidsafe/QA/raw/master/appveyor/install_rustup.ps1" 20 | Invoke-WebRequest $url -OutFile "install_rustup.ps1" 21 | . ".\install_rustup.ps1" 22 | 23 | platform: 24 | - x86 25 | - x64 26 | 27 | configuration: 28 | - Release 29 | 30 | build_script: 31 | - cargo check --verbose --release --lib --tests 32 | 33 | test_script: 34 | - |- 35 | cargo test --verbose --release 36 | cargo test --verbose --release --manifest-path rust_sodium-sys/Cargo.toml 37 | -------------------------------------------------------------------------------- /codeowners: -------------------------------------------------------------------------------- 1 | * @maidsafe/backend_codeowners 2 | -------------------------------------------------------------------------------- /rust_sodium-sys/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # rust_sodium-sys - Change Log 2 | 3 | ## [0.10.4] 4 | - upgrade libsodium to 1.0.17 5 | 6 | ## [0.10.3] 7 | - update lazy_static to 1.2.0 8 | - fix compilation with rustc 1.32.0 9 | 10 | ## [0.10.2] 11 | - add missing trait for MSVC build 12 | 13 | ## [0.10.1] 14 | - fix build: replace reqwest with http_req in build script 15 | - use rust 1.29.0 stable, drop nightly 16 | - use cargo fmt and cargo clippy 17 | 18 | ## [0.10.0] 19 | - upgrade unwrap version to 1.2.0 20 | - use rust 1.28.0 stable / 2018-07-07 nightly 21 | - rustfmt 0.99.2 and clippy-0.0.212 22 | 23 | ## [0.9.0] 24 | - upgrade libsodium version to 1.0.16 25 | - replace 'use-installed-libsodium' feature with env var 26 | - pull most outstanding sodiumoxide commits downstream 27 | - add a hash check of downloaded libsodium files to build script 28 | - use rust 1.25.0 stable 29 | 30 | ## [0.8.1] 31 | - update URL for libsodium sources 32 | 33 | ## [0.8.0] 34 | - Use rust 1.24.0 stable / 2018-02-05 nightly 35 | - rustfmt 0.9.0 and clippy-0.0.186 36 | 37 | ## [0.7.2] 38 | - Fix Android build error 39 | 40 | ## [0.7.1] 41 | - Fixed issue causing libsodium to be built unoptimised on non-Windows platforms 42 | 43 | ## [0.7.0] 44 | - Use rust 1.22.1 stable / 2017-11-23 nightly 45 | - rustfmt 0.9.0 and clippy-0.0.174 46 | 47 | ## [0.6.0] 48 | - Add support for iOS build targets 49 | 50 | ## [0.5.0] 51 | - Use rust 1.19 stable / 2017-07-20 nightly 52 | - rustfmt 0.9.0 and clippy-0.0.144 53 | - Replace -Zno-trans with cargo check 54 | - Make appveyor script using fixed version of stable 55 | 56 | ## [0.4.0] 57 | - Changed build script for non-Windows platforms to only pass `--disable-pie` when a new env var is set. 58 | 59 | ## [0.3.1] 60 | - Added fallback URL for Windows libsodium artefacts. 61 | 62 | ## [0.3.0] 63 | - Ported several updates from sodiumoxide 64 | - Upgraded libsodium version to 1.0.12 65 | - Changed the default feature behaviour for rust_sodium-sys to download and unpack/build libsodium 66 | - For Linux distros, only enable PIE for Ubuntu >= 15.04 67 | - Added support for MSVC builds 68 | - Changed to use rust 1.17 stable 69 | - Updated CI script to run cargo_install from QA 70 | 71 | ## [0.2.0] 72 | - Default to serde instead of rustc-serialize 73 | - rustfmt 0.8.1 74 | - enforce min powershell major version of 4 for compilation on Windows 75 | 76 | ## [0.1.2] 77 | - Fix Windows build scripts by using curl. 78 | - Fix ARM build by allowing the `trivial_casts` lint. 79 | - Print build commands on failure. 80 | - [Upstream pull - Make vector manipulation more efficient.](https://github.com/dnaq/sodiumoxide/commit/f509c90de1a5825abf67e1d8cd8cd70a35b91880) 81 | - Added `init()` to every test. 82 | - Updated dependencies. 83 | - Added standard MaidSafe lint checks and fixed resulting warnings. 84 | 85 | ## [0.1.1] 86 | - Bugfix for missed renaming of feature gate. 87 | 88 | ## [0.1.0] 89 | - Initial fork from sodiumoxide including changes to build script. 90 | - Added `init_with_rng()` to allow sodiumoxide_extras crate to be deprecated. 91 | -------------------------------------------------------------------------------- /rust_sodium-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["MaidSafe Developers "] 3 | build = "build.rs" 4 | categories = ["api-bindings", "cryptography"] 5 | description = "Raw bindings to libsodium" 6 | edition = "2018" 7 | homepage = "https://maidsafe.net" 8 | keywords = ["crypto", "cryptographic", "cryptography", "sodium"] 9 | license = "MIT OR BSD-3-Clause" 10 | links = "sodium" 11 | name = "rust_sodium-sys" 12 | repository = "https://github.com/maidsafe/rust_sodium" 13 | version = "0.10.4" 14 | 15 | [dependencies] 16 | lazy_static = "1.4.0" 17 | libc = "~0.2.40" 18 | rand = "~0.4.2" 19 | unwrap = "~1.2.0" 20 | 21 | [build-dependencies] 22 | cc = "~1.0.9" 23 | flate2 = "~1.0.1" 24 | libc = "~0.2.40" 25 | pkg-config = "~0.3.9" 26 | http_req = "~0.2.1" 27 | sha2 = "~0.7.0" 28 | tar = "~0.4.15" 29 | unwrap = "~1.2.0" 30 | zip = "~0.3.1" 31 | -------------------------------------------------------------------------------- /rust_sodium-sys/LICENSE-BSD: -------------------------------------------------------------------------------- 1 | Copyright 2018 MaidSafe.net limited. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | 3. Neither the name of copyright holder nor the 14 | names of its contributors may be used to endorse or promote products 15 | derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /rust_sodium-sys/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright for portions of rust_sodium are held by The 2 | sodiumoxide Developers, 2015 as part of sodiumoxide. All 3 | other copyright for rust_sodium are held by 4 | MaidSafe.net limited, 2016. 5 | 6 | Permission is hereby granted, free of charge, to any 7 | person obtaining a copy of this software and associated 8 | documentation files (the "Software"), to deal in the 9 | Software without restriction, including without 10 | limitation the rights to use, copy, modify, merge, 11 | publish, distribute, sublicense, and/or sell copies of 12 | the Software, and to permit persons to whom the Software 13 | is furnished to do so, subject to the following 14 | conditions: 15 | 16 | The above copyright notice and this permission notice 17 | shall be included in all copies or substantial portions 18 | of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 21 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 22 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 23 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 24 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 27 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 | DEALINGS IN THE SOFTWARE. 29 | -------------------------------------------------------------------------------- /rust_sodium-sys/README.md: -------------------------------------------------------------------------------- 1 | ## License 2 | 3 | This SAFE Network library is dual-licensed under the Modified BSD ([LICENSE-BSD](LICENSE-BSD) https://opensource.org/licenses/BSD-3-Clause) or the MIT license ([LICENSE-MIT](LICENSE-MIT) https://opensource.org/licenses/MIT) at your option. 4 | 5 | ## Contribution 6 | 7 | Copyrights in the SAFE Network are retained by their contributors. No copyright assignment is required to contribute to this project. -------------------------------------------------------------------------------- /rust_sodium-sys/src/seeded_rng.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | use super::{randombytes_implementation, randombytes_set_implementation, sodium_init}; 11 | use lazy_static::lazy_static; 12 | use libc; 13 | use rand::{self, Rng, SeedableRng, XorShiftRng}; 14 | use std::cell::RefCell; 15 | use std::ffi::CString; 16 | use std::rc::Rc; 17 | use std::sync::Mutex; 18 | use unwrap::unwrap; 19 | 20 | lazy_static! { 21 | static ref INIT_RESULT: Mutex> = Mutex::new(None); 22 | static ref RANDOM_BYTES_IMPL: Mutex = Mutex::new(RandomBytesImpl::default()); 23 | } 24 | 25 | thread_local!(static RNG: Rc> = 26 | Rc::new(RefCell::new(XorShiftRng::from_seed(unwrap!(RANDOM_BYTES_IMPL.lock()).seed)))); 27 | 28 | struct RandomBytesImpl { 29 | function_pointers: randombytes_implementation, 30 | name: CString, 31 | seed: [u32; 4], 32 | } 33 | 34 | impl Default for RandomBytesImpl { 35 | fn default() -> RandomBytesImpl { 36 | let seed = [ 37 | rand::random(), 38 | rand::random(), 39 | rand::random(), 40 | rand::random(), 41 | ]; 42 | RandomBytesImpl { 43 | function_pointers: randombytes_implementation::default(), 44 | name: unwrap!(CString::new("Rust XorShiftRng")), 45 | seed, 46 | } 47 | } 48 | } 49 | 50 | impl Default for randombytes_implementation { 51 | fn default() -> randombytes_implementation { 52 | randombytes_implementation { 53 | implementation_name: Some(implementation_name), 54 | random: Some(random), 55 | stir: None, 56 | uniform: None, 57 | buf: Some(buf), 58 | close: None, 59 | } 60 | } 61 | } 62 | 63 | extern "C" fn implementation_name() -> *const libc::c_char { 64 | unwrap!(RANDOM_BYTES_IMPL.lock()).name.as_ptr() 65 | } 66 | 67 | extern "C" fn random() -> u32 { 68 | RNG.with(|rng| rng.borrow_mut().gen()) 69 | } 70 | 71 | extern "C" fn buf(buf: *mut libc::c_void, size: usize) { 72 | unsafe { 73 | let ptr = buf as *mut u8; 74 | let rng_ptr = RNG.with(|rng| Rc::clone(rng)); 75 | let rng = &mut *rng_ptr.borrow_mut(); 76 | for i in 0..size { 77 | *ptr.add(i) = rng.gen(); 78 | } 79 | } 80 | } 81 | 82 | /// Sets [libsodium's `randombytes_implementation`][1] to use a 83 | /// [Rust `Rng` implementation](../rand/trait.Rng.html) and initialises libsodium. 84 | /// 85 | /// This allows a seeded PRNG to be used for example, which can be helpful in test scenarios when 86 | /// predictable results may be preferred. 87 | /// 88 | /// This function is safe to call multiple times concurrently from different threads. It will 89 | /// either always return `Ok` or will always return `Err`. 90 | /// 91 | /// The error will contain either `-1` or `1`. If the error is `-1`, the initialisation of 92 | /// libsodium has failed. If the error is `1`, libsodium has been successfully initialised 93 | /// elsewhere (e.g. via [`rust_sodium::init()`][2]) but this means that our attempt to apply this 94 | /// seeded RNG to libsodium has not been actioned. 95 | /// 96 | /// Each `rust_sodium` function which uses the random generator in a new thread will cause a new 97 | /// thread-local instance of the PRNG to be created. Each such instance will be seeded with the 98 | /// same value, meaning for example that two newly-spawned threads calling `box_::gen_keypair()` 99 | /// will generate identical keys. 100 | /// 101 | /// [1]: https://download.libsodium.org/doc/advanced/custom_rng.html 102 | /// [2]: https://docs.rs/rust_sodium/*/rust_sodium/fn.init.html 103 | pub fn init_with_rng(rng: &mut T) -> Result<(), i32> { 104 | let init_result = &mut *unwrap!(INIT_RESULT.lock()); 105 | if let Some(ref existing_result) = *init_result { 106 | return if *existing_result == 0 { 107 | Ok(()) 108 | } else { 109 | Err(*existing_result) 110 | }; 111 | } 112 | let mut sodium_result; 113 | let seed = [rng.gen(), rng.gen(), rng.gen(), rng.gen()]; 114 | { 115 | let random_bytes = &mut *unwrap!(RANDOM_BYTES_IMPL.lock()); 116 | random_bytes.seed = seed; 117 | sodium_result = 118 | unsafe { randombytes_set_implementation(&mut random_bytes.function_pointers) }; 119 | } 120 | if sodium_result == 0 { 121 | sodium_result = unsafe { sodium_init() }; 122 | } 123 | // Since `sodium_init()` makes a call to `buf()`, reset the thread-local `RNG` so that it yields 124 | // consistent results with calls from new threads. 125 | RNG.with(|rng| *rng.borrow_mut() = XorShiftRng::from_seed(seed)); 126 | *init_result = Some(sodium_result); 127 | match sodium_result { 128 | 0 => Ok(()), 129 | result => Err(result), 130 | } 131 | } 132 | 133 | #[cfg(test)] 134 | mod tests { 135 | use super::*; 136 | use crate::{ 137 | crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES, 138 | crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES, 139 | crypto_box_curve25519xsalsa20poly1305_keypair, 140 | }; 141 | 142 | #[test] 143 | #[rustfmt::skip] 144 | fn seeded_init_with_rng() { 145 | use std::thread::Builder; 146 | let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); 147 | unwrap!(init_with_rng(&mut rng)); 148 | 149 | // Initialise again - should succeed. 150 | unwrap!(init_with_rng(&mut rng)); 151 | 152 | let expected_public_key = [116, 196, 172, 118, 77, 124, 253, 254, 156, 51, 141, 193, 20, 153 | 160, 227, 232, 231, 20, 24, 151, 207, 45, 202, 250, 85, 96, 206, 144, 170, 185, 192, 154 | 101, ]; 155 | let expected_secret_key = [24, 74, 130, 137, 89, 75, 193, 8, 153, 136, 7, 141, 220, 198, 156 | 207, 232, 228, 74, 189, 36, 9, 209, 239, 95, 69, 207, 163, 2, 37, 237, 255, 64, ]; 157 | let mut public_key = [0u8; crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES as usize]; 158 | let mut secret_key = [0u8; crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES as usize]; 159 | unsafe { 160 | assert_eq!( 161 | crypto_box_curve25519xsalsa20poly1305_keypair( 162 | public_key.as_mut_ptr(), 163 | secret_key.as_mut_ptr(), 164 | ), 165 | 0 166 | ); 167 | } 168 | assert_eq!(expected_public_key, public_key); 169 | assert_eq!(expected_secret_key, secret_key); 170 | 171 | let child1 = unwrap!(Builder::new().name("child1".to_string()).spawn(move || { 172 | let mut public_key = [0; crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES as usize]; 173 | let mut secret_key = [0; crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES as usize]; 174 | unsafe { 175 | assert_eq!( 176 | crypto_box_curve25519xsalsa20poly1305_keypair( 177 | public_key.as_mut_ptr(), 178 | secret_key.as_mut_ptr(), 179 | ), 180 | 0 181 | ); 182 | } 183 | assert_eq!(expected_public_key, public_key); 184 | assert_eq!(expected_secret_key, secret_key); 185 | })); 186 | let child2 = unwrap!(Builder::new().name("child2".to_string()).spawn(move || { 187 | let mut public_key = [0; crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES as usize]; 188 | let mut secret_key = [0; crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES as usize]; 189 | unsafe { 190 | assert_eq!( 191 | crypto_box_curve25519xsalsa20poly1305_keypair( 192 | public_key.as_mut_ptr(), 193 | secret_key.as_mut_ptr(), 194 | ), 195 | 0 196 | ); 197 | } 198 | assert_eq!(expected_public_key, public_key); 199 | assert_eq!(expected_secret_key, secret_key); 200 | })); 201 | unwrap!(child1.join()); 202 | unwrap!(child2.join()); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | use_try_shorthand = true 2 | -------------------------------------------------------------------------------- /src/crypto/aead/aead_macros.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | macro_rules! aead_module (($seal_name:ident, 11 | $open_name:ident, 12 | $seal_detached_name:ident, 13 | $open_detached_name:ident, 14 | $keybytes:expr, 15 | $noncebytes:expr, 16 | $tagbytes:expr) => ( 17 | 18 | use libc::c_ulonglong; 19 | use crate::randombytes::randombytes_into; 20 | use std::ptr; 21 | 22 | /// Number of bytes in a `Key`. 23 | pub const KEYBYTES: usize = $keybytes; 24 | 25 | /// Number of bytes in a `Nonce`. 26 | pub const NONCEBYTES: usize = $noncebytes; 27 | 28 | /// Number of bytes in an authentication `Tag`. 29 | pub const TAGBYTES: usize = $tagbytes; 30 | 31 | new_type! { 32 | /// `Key` for symmetric authenticated encryption with additional data. 33 | /// 34 | /// When a `Key` goes out of scope its contents will 35 | /// be zeroed out 36 | secret Key(KEYBYTES); 37 | } 38 | 39 | new_type! { 40 | /// `Nonce` for symmetric authenticated encryption with additional data. 41 | nonce Nonce(NONCEBYTES); 42 | } 43 | 44 | new_type! { 45 | /// Authentication `Tag` for symmetric authenticated encryption with additional data in 46 | /// detached mode. 47 | public Tag(TAGBYTES); 48 | } 49 | 50 | /// `gen_key()` randomly generates a secret key 51 | /// 52 | /// THREAD SAFETY: `gen_key()` is thread-safe provided that you have 53 | /// called `rust_sodium::init()` once before using any other function 54 | /// from `rust_sodium`. 55 | pub fn gen_key() -> Key { 56 | let mut k = Key([0u8; KEYBYTES]); 57 | randombytes_into(&mut k.0); 58 | k 59 | } 60 | 61 | /// `gen_nonce()` randomly generates a nonce 62 | /// 63 | /// THREAD SAFETY: `gen_key()` is thread-safe provided that you have 64 | /// called `rust_sodium::init()` once before using any other function 65 | /// from `rust_sodium`. 66 | pub fn gen_nonce() -> Nonce { 67 | let mut n = Nonce([0u8; NONCEBYTES]); 68 | randombytes_into(&mut n.0); 69 | n 70 | } 71 | 72 | /// `seal()` encrypts and authenticates a message `m` together with optional plaintext data `ad` 73 | /// using a secret key `k` and a nonce `n`. It returns a ciphertext `c`. 74 | pub fn seal(m: &[u8], ad: Option<&[u8]>, n: &Nonce, k: &Key) -> Vec { 75 | let (ad_p, ad_len) = ad.map(|ad| (ad.as_ptr(), ad.len() as c_ulonglong)) 76 | .unwrap_or((ptr::null(), 0)); 77 | let mut c = Vec::with_capacity(m.len() + TAGBYTES); 78 | let mut clen = c.len() as c_ulonglong; 79 | 80 | unsafe { 81 | let _ = $seal_name( 82 | c.as_mut_ptr(), 83 | &mut clen, 84 | m.as_ptr(), 85 | m.len() as c_ulonglong, 86 | ad_p, 87 | ad_len, 88 | ptr::null_mut(), 89 | n.0.as_ptr(), 90 | k.0.as_ptr() 91 | ); 92 | c.set_len(clen as usize); 93 | } 94 | c 95 | } 96 | 97 | /// `seal_detached()` encrypts and authenticates a message `m` together with optional plaintext data 98 | /// `ad` using a secret key `k` and a nonce `n`. 99 | /// `m` is encrypted in place, so after this function returns it will contain the ciphertext. 100 | /// The detached authentication tag is returned by value. 101 | pub fn seal_detached(m: &mut [u8], ad: Option<&[u8]>, n: &Nonce, k: &Key) -> Tag { 102 | let (ad_p, ad_len) = ad.map(|ad| (ad.as_ptr(), ad.len() as c_ulonglong)) 103 | .unwrap_or((ptr::null(), 0)); 104 | let mut tag = Tag([0u8; TAGBYTES]); 105 | let mut maclen = TAGBYTES as c_ulonglong; 106 | unsafe { 107 | let _ = $seal_detached_name( 108 | m.as_mut_ptr(), 109 | tag.0.as_mut_ptr(), 110 | &mut maclen, 111 | m.as_ptr(), 112 | m.len() as c_ulonglong, 113 | ad_p, 114 | ad_len, 115 | ptr::null_mut(), 116 | n.0.as_ptr(), 117 | k.0.as_ptr() 118 | ); 119 | } 120 | tag 121 | } 122 | 123 | /// `open()` verifies and decrypts a ciphertext `c` together with optional plaintext data `ad` 124 | /// using a secret key `k` and a nonce `n`. 125 | /// It returns a plaintext `Ok(m)`. 126 | /// If the ciphertext fails verification, `open()` returns `Err(())`. 127 | pub fn open(c: &[u8], ad: Option<&[u8]>, n: &Nonce, k: &Key) -> Result, ()> { 128 | if c.len() < TAGBYTES { 129 | return Err(()); 130 | } 131 | let (ad_p, ad_len) = ad.map(|ad| (ad.as_ptr(), ad.len() as c_ulonglong)) 132 | .unwrap_or((ptr::null(), 0)); 133 | let mut m = Vec::with_capacity(c.len() - TAGBYTES); 134 | let mut mlen = m.len() as c_ulonglong; 135 | 136 | unsafe { 137 | let ret = 138 | $open_name( 139 | m.as_mut_ptr(), 140 | &mut mlen, 141 | ptr::null_mut(), 142 | c.as_ptr(), 143 | c.len() as c_ulonglong, 144 | ad_p, 145 | ad_len, 146 | n.0.as_ptr(), 147 | k.0.as_ptr() 148 | ); 149 | if ret != 0 { 150 | return Err(()); 151 | } 152 | m.set_len(mlen as usize); 153 | } 154 | Ok(m) 155 | } 156 | /// `open_detached()` verifies and decrypts a ciphertext `c` toghether with optional plaintext data 157 | /// `ad` and and authentication tag `tag`, using a secret key `k` and a nonce `n`. 158 | /// `c` is decrypted in place, so if this function is successful it will contain the plaintext. 159 | /// If the ciphertext fails verification, `open_detached()` returns `Err(())`, 160 | /// and the ciphertext is not modified. 161 | pub fn open_detached( 162 | c: &mut [u8], 163 | ad: Option<&[u8]>, 164 | t: &Tag, 165 | n: &Nonce, 166 | k: &Key, 167 | ) -> Result<(), ()> { 168 | let (ad_p, ad_len) = ad.map(|ad| (ad.as_ptr(), ad.len() as c_ulonglong)) 169 | .unwrap_or((ptr::null(), 0)); 170 | let ret = unsafe { 171 | $open_detached_name( 172 | c.as_mut_ptr(), 173 | ptr::null_mut(), 174 | c.as_ptr(), 175 | c.len() as c_ulonglong, 176 | t.0.as_ptr(), 177 | ad_p, 178 | ad_len, 179 | n.0.as_ptr(), 180 | k.0.as_ptr() 181 | ) 182 | }; 183 | if ret == 0 { 184 | Ok(()) 185 | } else { 186 | Err(()) 187 | } 188 | } 189 | 190 | #[cfg(test)] 191 | mod test_m { 192 | use super::*; 193 | 194 | #[test] 195 | fn test_seal_open() { 196 | use crate::randombytes::randombytes; 197 | unwrap!(crate::init()); 198 | for i in 0..256usize { 199 | let k = gen_key(); 200 | let n = gen_nonce(); 201 | let ad = randombytes(i); 202 | let m = randombytes(i); 203 | let c = seal(&m, Some(&ad), &n, &k); 204 | let m2 = unwrap!(open(&c, Some(&ad), &n, &k)); 205 | assert_eq!(m, m2); 206 | } 207 | } 208 | 209 | #[test] 210 | fn test_seal_open_tamper() { 211 | use crate::randombytes::randombytes; 212 | unwrap!(crate::init()); 213 | for i in 0..32usize { 214 | let k = gen_key(); 215 | let n = gen_nonce(); 216 | let mut ad = randombytes(i); 217 | let m = randombytes(i); 218 | let mut c = seal(&m, Some(&ad), &n, &k); 219 | for j in 0..c.len() { 220 | c[j] ^= 0x20; 221 | let m2 = open(&c, Some(&ad), &n, &k); 222 | c[j] ^= 0x20; 223 | assert!(m2.is_err()); 224 | } 225 | for j in 0..ad.len() { 226 | ad[j] ^= 0x20; 227 | let m2 = open(&c, Some(&ad), &n, &k); 228 | ad[j] ^= 0x20; 229 | assert!(m2.is_err()); 230 | } 231 | } 232 | } 233 | 234 | #[test] 235 | fn test_seal_open_detached() { 236 | use crate::randombytes::randombytes; 237 | unwrap!(crate::init()); 238 | for i in 0..256usize { 239 | let k = gen_key(); 240 | let n = gen_nonce(); 241 | let ad = randombytes(i); 242 | let mut m = randombytes(i); 243 | let m2 = m.clone(); 244 | let t = seal_detached(&mut m, Some(&ad), &n, &k); 245 | unwrap!(open_detached(&mut m, Some(&ad), &t, &n, &k)); 246 | assert_eq!(m, m2); 247 | } 248 | } 249 | 250 | #[test] 251 | fn test_seal_open_detached_tamper() { 252 | use crate::randombytes::randombytes; 253 | unwrap!(crate::init()); 254 | for i in 0..32usize { 255 | let k = gen_key(); 256 | let n = gen_nonce(); 257 | let mut ad = randombytes(i); 258 | let mut m = randombytes(i); 259 | let mut t = seal_detached(&mut m, Some(&ad), &n, &k); 260 | for j in 0..m.len() { 261 | m[j] ^= 0x20; 262 | let r = open_detached(&mut m, Some(&ad), &t, &n, &k); 263 | m[j] ^= 0x20; 264 | assert!(r.is_err()); 265 | } 266 | for j in 0..ad.len() { 267 | ad[j] ^= 0x20; 268 | let r = open_detached(&mut m, Some(&ad), &t, &n, &k); 269 | ad[j] ^= 0x20; 270 | assert!(r.is_err()); 271 | } 272 | for j in 0..t.0.len() { 273 | t.0[j] ^= 0x20; 274 | let r = open_detached(&mut m, Some(&ad), &t, &n, &k); 275 | t.0[j] ^= 0x20; 276 | assert!(r.is_err()); 277 | } 278 | } 279 | } 280 | 281 | #[test] 282 | fn test_seal_open_detached_same() { 283 | use crate::randombytes::randombytes; 284 | unwrap!(crate::init()); 285 | for i in 0..256usize { 286 | let k = gen_key(); 287 | let n = gen_nonce(); 288 | let ad = randombytes(i); 289 | let mut m = randombytes(i); 290 | 291 | let c = seal(&m, Some(&ad), &n, &k); 292 | let t = seal_detached(&mut m, Some(&ad), &n, &k); 293 | 294 | assert_eq!(&c[0..c.len()-TAGBYTES], &m[..]); 295 | assert_eq!(&c[c.len()-TAGBYTES..], &t.0[..]); 296 | 297 | let m2 = unwrap!(open(&c, Some(&ad), &n, &k)); 298 | unwrap!(open_detached(&mut m, Some(&ad), &t, &n, &k)); 299 | 300 | assert_eq!(m2, m); 301 | } 302 | } 303 | } 304 | 305 | )); 306 | -------------------------------------------------------------------------------- /src/crypto/aead/chacha20poly1305.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! The original ChaCha20-Poly1305 construction can safely encrypt a pratically 11 | //! unlimited number of messages with the same key, without any practical limit 12 | //! to the size of a message (up to ~ 2^64 bytes). 13 | 14 | use crate::ffi::{ 15 | crypto_aead_chacha20poly1305_ABYTES, crypto_aead_chacha20poly1305_KEYBYTES, 16 | crypto_aead_chacha20poly1305_NPUBBYTES, crypto_aead_chacha20poly1305_decrypt, 17 | crypto_aead_chacha20poly1305_decrypt_detached, crypto_aead_chacha20poly1305_encrypt, 18 | crypto_aead_chacha20poly1305_encrypt_detached, 19 | }; 20 | aead_module!( 21 | crypto_aead_chacha20poly1305_encrypt, 22 | crypto_aead_chacha20poly1305_decrypt, 23 | crypto_aead_chacha20poly1305_encrypt_detached, 24 | crypto_aead_chacha20poly1305_decrypt_detached, 25 | crypto_aead_chacha20poly1305_KEYBYTES as usize, 26 | crypto_aead_chacha20poly1305_NPUBBYTES as usize, 27 | crypto_aead_chacha20poly1305_ABYTES as usize 28 | ); 29 | 30 | #[cfg(test)] 31 | mod test { 32 | use super::*; 33 | 34 | #[test] 35 | #[rustfmt::skip] 36 | fn test_vector_1() { 37 | // Test from https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7 38 | unwrap!(crate::init()); 39 | let m = &[0x86, 0xd0, 0x99, 0x74, 0x84, 0x0b, 0xde, 0xd2, 0xa5, 0xca]; 40 | let k = Key([ 41 | 0x42, 0x90, 0xbc, 0xb1, 0x54, 0x17, 0x35, 0x31, 0xf3, 0x14, 0xaf, 0x57, 0xf3, 0xbe, 42 | 0x3b, 0x50, 0x06, 0xda, 0x37, 0x1e, 0xce, 0x27, 0x2a, 0xfa, 0x1b, 0x5d, 0xbd, 0xd1, 43 | 0x10, 0x0a, 0x10, 0x07]); 44 | let n = Nonce([0xcd, 0x7c, 0xf6, 0x7b, 0xe3, 0x9c, 0x79, 0x4a]); 45 | let ad = &[0x87, 0xe2, 0x29, 0xd4, 0x50, 0x08, 0x45, 0xa0, 0x79, 0xc0]; 46 | 47 | let c_expected = &[0xe3, 0xe4, 0x46, 0xf7, 0xed, 0xe9, 0xa1, 0x9b, 0x62, 0xa4, 0x67, 48 | 0x7d, 0xab, 0xf4, 0xe3, 0xd2, 0x4b, 0x87, 0x6b, 0xb2, 0x84, 0x75, 0x38, 0x96, 0xe1, 49 | 0xd6]; 50 | 51 | let c = seal(m, Some(ad), &n, &k); 52 | assert_eq!(&c[..], c_expected); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/crypto/aead/chacha20poly1305_ietf.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! The IETF variant of the ChaCha20-Poly1305 construction can safely encrypt a 11 | //! practically unlimited number of messages, but individual messages cannot 12 | //! exceed 64*(2^32)-64 bytes (approximatively 256 GB). 13 | 14 | use crate::ffi::{ 15 | crypto_aead_chacha20poly1305_ietf_ABYTES, crypto_aead_chacha20poly1305_ietf_KEYBYTES, 16 | crypto_aead_chacha20poly1305_ietf_NPUBBYTES, crypto_aead_chacha20poly1305_ietf_decrypt, 17 | crypto_aead_chacha20poly1305_ietf_decrypt_detached, crypto_aead_chacha20poly1305_ietf_encrypt, 18 | crypto_aead_chacha20poly1305_ietf_encrypt_detached, 19 | }; 20 | aead_module!( 21 | crypto_aead_chacha20poly1305_ietf_encrypt, 22 | crypto_aead_chacha20poly1305_ietf_decrypt, 23 | crypto_aead_chacha20poly1305_ietf_encrypt_detached, 24 | crypto_aead_chacha20poly1305_ietf_decrypt_detached, 25 | crypto_aead_chacha20poly1305_ietf_KEYBYTES as usize, 26 | crypto_aead_chacha20poly1305_ietf_NPUBBYTES as usize, 27 | crypto_aead_chacha20poly1305_ietf_ABYTES as usize 28 | ); 29 | 30 | #[cfg(test)] 31 | mod test { 32 | use super::*; 33 | 34 | #[test] 35 | #[rustfmt::skip] 36 | fn test_vector_1() { 37 | // Test vector from https://tools.ietf.org/html/rfc7539#section-2.8.1 38 | unwrap!(crate::init()); 39 | let m = &[0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 40 | 0x6e, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 41 | 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 42 | 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 43 | 0x66, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 44 | 0x6e, 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 45 | 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, 0x63, 46 | 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 47 | 0x69, 0x74, 0x2e]; 48 | let ad = &[0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7]; 49 | let k = Key([0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 50 | 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 51 | 0x9b, 0x9c, 0x9d, 0x9e, 0x9f]); 52 | let n = Nonce([0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47]); 53 | 54 | let c_expected = &[0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 0x7b, 0x86, 0xaf, 0xbc, 55 | 0x53, 0xef, 0x7e, 0xc2, 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, 0xa9, 0xe2, 56 | 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, 57 | 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 58 | 0x0b, 0x29, 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, 0x92, 0xdd, 0xbd, 0x7f, 59 | 0x2d, 0x77, 0x8b, 0x8c, 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 0xfa, 0xb3, 60 | 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, 61 | 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 62 | 0xc6, 0x4b, 0x61, 0x16, 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, 0x7e, 0x90, 63 | 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91]; 64 | let c = seal(m, Some(ad), &n, &k); 65 | assert_eq!(&c[..], &c_expected[..]); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/crypto/aead/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Authenticated Encryption with Additional Data 11 | //! This operation: 12 | //! 13 | //! - Encrypts a message with a key and a nonce to keep it confidential 14 | //! - Computes an authentication tag. This tag is used to make sure that the message, 15 | //! as well as optional, non-confidential (non-encrypted) data, haven't been tampered with. 16 | //! 17 | //! # Selected primitive 18 | //! `seal()`, `seal_detached()`, `open()` and `open_detached()` are currently 19 | //! an implementation of `chacha20poly1305_ietf`, i.e. the IETF construction defined in 20 | //! 21 | //! 22 | //! # Example (combined mode) 23 | //! ``` 24 | //! use rust_sodium::crypto::aead; 25 | //! 26 | //! let k = aead::gen_key(); 27 | //! let n = aead::gen_nonce(); 28 | //! let m = b"Some plaintext"; 29 | //! let ad = b"Some additional data"; 30 | //! 31 | //! let c = aead::seal(m, Some(ad), &n, &k); 32 | //! let m2 = aead::open(&c, Some(ad), &n, &k).unwrap(); 33 | //! 34 | //! assert_eq!(&m[..], &m2[..]); 35 | //!``` 36 | //! 37 | //! # Example (detached mode) 38 | //! ``` 39 | //! use rust_sodium::crypto::aead; 40 | //! 41 | //! let k = aead::gen_key(); 42 | //! let n = aead::gen_nonce(); 43 | //! let mut m = [0x41, 0x42, 0x43, 0x44]; 44 | //! let m2 = m.clone(); 45 | //! let ad = b"Some additional data"; 46 | //! 47 | //! let t = aead::seal_detached(&mut m, Some(ad), &n, &k); 48 | //! aead::open_detached(&mut m, Some(ad), &t, &n, &k).unwrap(); 49 | //! 50 | //! assert_eq!(m, m2); 51 | //! ``` 52 | 53 | pub use self::chacha20poly1305_ietf::*; 54 | #[macro_use] 55 | mod aead_macros; 56 | pub mod chacha20poly1305; 57 | pub mod chacha20poly1305_ietf; 58 | -------------------------------------------------------------------------------- /src/crypto/auth/auth_macros.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | macro_rules! auth_module (($auth_name:ident, 11 | $verify_name:ident, 12 | $keybytes:expr, 13 | $tagbytes:expr) => ( 14 | 15 | use libc::c_ulonglong; 16 | use crate::randombytes::randombytes_into; 17 | 18 | /// Number of bytes in a `Key`. 19 | pub const KEYBYTES: usize = $keybytes; 20 | 21 | /// Number of bytes in a `Tag`. 22 | pub const TAGBYTES: usize = $tagbytes; 23 | 24 | new_type! { 25 | /// Authentication `Key` 26 | /// 27 | /// When a `Key` goes out of scope its contents 28 | /// will be zeroed out 29 | secret Key(KEYBYTES); 30 | } 31 | 32 | new_type! { 33 | /// Authentication `Tag` 34 | /// 35 | /// The tag implements the traits `PartialEq` and `Eq` using constant-time 36 | /// comparison functions. See `rust_sodium::utils::memcmp` 37 | public Tag(TAGBYTES); 38 | } 39 | 40 | /// `gen_key()` randomly generates a key for authentication 41 | /// 42 | /// THREAD SAFETY: `gen_key()` is thread-safe provided that you have 43 | /// called `rust_sodium::init()` once before using any other function 44 | /// from `rust_sodium`. 45 | pub fn gen_key() -> Key { 46 | let mut k = [0; KEYBYTES]; 47 | randombytes_into(&mut k); 48 | Key(k) 49 | } 50 | 51 | /// `authenticate()` authenticates a message `m` using a secret key `k`. 52 | /// The function returns an authenticator tag. 53 | pub fn authenticate(m: &[u8], 54 | &Key(ref k): &Key) -> Tag { 55 | unsafe { 56 | let mut tag = [0; TAGBYTES]; 57 | let _todo_use_result = $auth_name(tag.as_mut_ptr(), 58 | m.as_ptr(), 59 | m.len() as c_ulonglong, 60 | k.as_ptr()); 61 | Tag(tag) 62 | } 63 | } 64 | 65 | /// `verify()` returns `true` if `tag` is a correct authenticator of message `m` 66 | /// under a secret key `k`. Otherwise it returns false. 67 | pub fn verify(&Tag(ref tag): &Tag, m: &[u8], 68 | &Key(ref k): &Key) -> bool { 69 | unsafe { 70 | $verify_name(tag.as_ptr(), 71 | m.as_ptr(), 72 | m.len() as c_ulonglong, 73 | k.as_ptr()) == 0 74 | } 75 | } 76 | 77 | #[cfg(test)] 78 | mod test_m { 79 | use super::*; 80 | 81 | #[test] 82 | fn test_auth_verify() { 83 | use crate::randombytes::randombytes; 84 | unwrap!(crate::init()); 85 | for i in 0..256usize { 86 | let k = gen_key(); 87 | let m = randombytes(i); 88 | let tag = authenticate(&m, &k); 89 | assert!(verify(&tag, &m, &k)); 90 | } 91 | } 92 | 93 | #[test] 94 | fn test_auth_verify_tamper() { 95 | use crate::randombytes::randombytes; 96 | unwrap!(crate::init()); 97 | for i in 0..32usize { 98 | let k = gen_key(); 99 | let mut m = randombytes(i); 100 | let Tag(mut tagbuf) = authenticate(&m, &k); 101 | for j in 0..m.len() { 102 | m[j] ^= 0x20; 103 | assert!(!verify(&Tag(tagbuf), &m, &k)); 104 | m[j] ^= 0x20; 105 | } 106 | for j in 0..tagbuf.len() { 107 | tagbuf[j] ^= 0x20; 108 | assert!(!verify(&Tag(tagbuf), &m, &k)); 109 | tagbuf[j] ^= 0x20; 110 | } 111 | } 112 | } 113 | 114 | #[test] 115 | fn test_serialisation() { 116 | use crate::randombytes::randombytes; 117 | use crate::test_utils::round_trip; 118 | unwrap!(crate::init()); 119 | for i in 0..256usize { 120 | let k = gen_key(); 121 | let m = randombytes(i); 122 | let tag = authenticate(&m, &k); 123 | round_trip(&k); 124 | round_trip(&tag); 125 | } 126 | } 127 | } 128 | 129 | #[cfg(feature = "benchmarks")] 130 | #[cfg(test)] 131 | mod bench_m { 132 | extern crate test; 133 | use crate::randombytes::randombytes; 134 | use super::*; 135 | 136 | const BENCH_SIZES: [usize; 14] = [0, 1, 2, 4, 8, 16, 32, 64, 137 | 128, 256, 512, 1024, 2048, 4096]; 138 | 139 | #[bench] 140 | fn bench_auth(b: &mut test::Bencher) { 141 | unwrap!(crate::init()); 142 | let k = gen_key(); 143 | let ms: Vec> = BENCH_SIZES.iter().map(|s| { 144 | randombytes(*s) 145 | }).collect(); 146 | b.iter(|| { 147 | for m in ms.iter() { 148 | authenticate(&m, &k); 149 | } 150 | }); 151 | } 152 | 153 | #[bench] 154 | fn bench_verify(b: &mut test::Bencher) { 155 | unwrap!(crate::init()); 156 | let k = gen_key(); 157 | let ms: Vec> = BENCH_SIZES.iter().map(|s| { 158 | randombytes(*s) 159 | }).collect(); 160 | let tags: Vec = ms.iter().map(|m| { 161 | authenticate(&m, &k) 162 | }).collect(); 163 | b.iter(|| { 164 | for (m, t) in ms.iter().zip(tags.iter()) { 165 | verify(t, &m, &k); 166 | } 167 | }); 168 | } 169 | } 170 | 171 | )); 172 | 173 | /// Macro for defining streaming authenticator tag computation types and functions. 174 | /// 175 | /// Parameters: 176 | /// `$state_name` - The authenticator state type. 177 | /// SAFETY NOTE: This needs to be a type that does not define a `Drop` 178 | /// implementation, otherwise undefined behaviour will occur. 179 | /// `$init_name` - A function `f(s: *mut $state_name, k: *u8, klen: size_t)` that initializes 180 | /// a state with a key. 181 | /// `$update_name` - A function `f(s: *mut $state_name, m: *u8, mlen: size_t)` that updates 182 | /// a state with a message chunk. 183 | /// `$final_name` - A function `f(s: *mut $state_name, t: *u8)` that computes an authenticator 184 | /// tag of length `$tagbytes` from a `$state_name`. 185 | /// `$tagbytes` - The number of bytes in an authenticator tag. 186 | #[allow(unused)] 187 | macro_rules! auth_state (($state_name:ident, 188 | $init_name:ident, 189 | $update_name:ident, 190 | $final_name:ident, 191 | $tagbytes:expr) => ( 192 | 193 | use std::mem; 194 | use crate::ffi; 195 | 196 | /// Authentication `State` 197 | /// 198 | /// State for multi-part (streaming) authenticator tag (HMAC) computation. 199 | /// 200 | /// When a `State` goes out of scope its contents will be zeroed out. 201 | /// 202 | /// NOTE: the streaming interface takes variable length keys, as opposed to the 203 | /// simple interface which takes a fixed length key. The streaming interface also does not 204 | /// define its own `Key` type, instead using slices for its `init()` method. 205 | /// The caller of the functions is responsible for zeroing out the key after it's been used 206 | /// (in contrast to the simple interface which defines a `Drop` implementation for `Key`). 207 | /// 208 | /// NOTE: these functions are specific to `libsodium` and do not exist in `NaCl`. 209 | 210 | #[must_use] 211 | pub struct State($state_name); 212 | 213 | impl Drop for State { 214 | fn drop(&mut self) { 215 | use libc::c_void; 216 | let &mut State(ref mut s) = self; 217 | unsafe { 218 | let sp: *mut $state_name = s; 219 | ffi::sodium_memzero(sp as *mut c_void, mem::size_of_val(s)); 220 | } 221 | } 222 | } 223 | 224 | impl State { 225 | /// `init()` initializes an authentication structure using a secret key 'k'. 226 | pub fn init(k: &[u8]) -> State { 227 | unsafe { 228 | let mut s = mem::uninitialized(); 229 | let _todo_use_result = $init_name(&mut s, k.as_ptr(), k.len()); 230 | State(s) 231 | } 232 | } 233 | 234 | /// `update()` can be called more than once in order to compute the authenticator 235 | /// from sequential chunks of the message. 236 | pub fn update(&mut self, in_: &[u8]) { 237 | unsafe { 238 | let _ = $update_name(&mut self.0, in_.as_ptr(), in_.len() as c_ulonglong); 239 | } 240 | } 241 | 242 | /// `finalize()` finalizes the authenticator computation and returns a `Tag`. `finalize` 243 | /// consumes the `State` so that it cannot be accidentally reused. 244 | #[allow(trivial_numeric_casts)] 245 | pub fn finalize(mut self) -> Tag { 246 | unsafe { 247 | let mut tag = [0; $tagbytes as usize]; 248 | let _ = $final_name(&mut self.0, tag.as_mut_ptr()); 249 | Tag(tag) 250 | } 251 | } 252 | } 253 | 254 | #[cfg(test)] 255 | mod test_s { 256 | use super::*; 257 | 258 | #[test] 259 | fn test_auth_eq_auth_state() { 260 | use crate::randombytes::randombytes; 261 | unwrap!(crate::init()); 262 | for i in 0..256usize { 263 | let k = gen_key(); 264 | let m = randombytes(i); 265 | let tag = authenticate(&m, &k); 266 | let mut state = State::init(&k[..]); 267 | state.update(&m); 268 | let tag2 = state.finalize(); 269 | assert_eq!(tag, tag2); 270 | } 271 | } 272 | 273 | #[test] 274 | fn test_auth_eq_auth_state_chunked() { 275 | use crate::randombytes::randombytes; 276 | unwrap!(crate::init()); 277 | for i in 0..256usize { 278 | let k = gen_key(); 279 | let m = randombytes(i); 280 | let tag = authenticate(&m, &k); 281 | let mut state = State::init(&k[..]); 282 | for c in m.chunks(1) { 283 | state.update(c); 284 | } 285 | let tag2 = state.finalize(); 286 | assert_eq!(tag, tag2); 287 | } 288 | } 289 | } 290 | )); 291 | -------------------------------------------------------------------------------- /src/crypto/auth/hmacsha256.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! `HMAC-SHA-256` `HMAC-SHA-256` is conjectured to meet the standard notion of 11 | //! unforgeability. 12 | 13 | use crate::ffi::{ 14 | crypto_auth_hmacsha256, crypto_auth_hmacsha256_BYTES, crypto_auth_hmacsha256_KEYBYTES, 15 | crypto_auth_hmacsha256_final, crypto_auth_hmacsha256_init, crypto_auth_hmacsha256_state, 16 | crypto_auth_hmacsha256_update, crypto_auth_hmacsha256_verify, 17 | }; 18 | 19 | auth_module!( 20 | crypto_auth_hmacsha256, 21 | crypto_auth_hmacsha256_verify, 22 | crypto_auth_hmacsha256_KEYBYTES as usize, 23 | crypto_auth_hmacsha256_BYTES as usize 24 | ); 25 | 26 | auth_state!( 27 | crypto_auth_hmacsha256_state, 28 | crypto_auth_hmacsha256_init, 29 | crypto_auth_hmacsha256_update, 30 | crypto_auth_hmacsha256_final, 31 | crypto_auth_hmacsha256_BYTES 32 | ); 33 | 34 | #[cfg(test)] 35 | #[rustfmt::skip] 36 | mod test { 37 | use super::*; 38 | 39 | #[test] 40 | fn test_vector_1() { 41 | // corresponding to tests/auth2.c from NaCl 42 | unwrap!(crate::init()); 43 | let key = Key([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 44 | 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 45 | 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20]); 46 | let c = [0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 47 | 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 48 | 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 49 | 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd]; 50 | let a_expected = Tag([0x37, 0x2e, 0xfc, 0xf9, 0xb4, 0x0b, 0x35, 0xc2, 0x11, 0x5b, 0x13, 51 | 0x46, 0x90, 0x3d, 0x2e, 0xf4, 0x2f, 0xce, 0xd4, 0x6f, 0x08, 0x46, 52 | 0xe7, 0x25, 0x7b, 0xb1, 0x56, 0xd3, 0xd7, 0xb3, 0x0d, 0x3f]); 53 | let a = authenticate(&c, &key); 54 | assert!(a == a_expected); 55 | } 56 | 57 | #[test] 58 | fn test_vector_state_1() { 59 | // corresponding to tests/auth2.c from NaCl 60 | unwrap!(crate::init()); 61 | let key = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 62 | 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 63 | 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20]; 64 | let c = [0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 65 | 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 66 | 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 67 | 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd]; 68 | let a_expected = Tag([0x37, 0x2e, 0xfc, 0xf9, 0xb4, 0x0b, 0x35, 0xc2, 0x11, 0x5b, 0x13, 69 | 0x46, 0x90, 0x3d, 0x2e, 0xf4, 0x2f, 0xce, 0xd4, 0x6f, 0x08, 0x46, 70 | 0xe7, 0x25, 0x7b, 0xb1, 0x56, 0xd3, 0xd7, 0xb3, 0x0d, 0x3f]); 71 | let mut state = State::init(&key); 72 | state.update(&c); 73 | let a = state.finalize(); 74 | assert!(a == a_expected); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/crypto/auth/hmacsha512.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! `HMAC-SHA-512` `HMAC-SHA-512` is conjectured to meet the standard notion of 11 | //! unforgeability. 12 | 13 | use crate::ffi::{ 14 | crypto_auth_hmacsha512, crypto_auth_hmacsha512_BYTES, crypto_auth_hmacsha512_KEYBYTES, 15 | crypto_auth_hmacsha512_final, crypto_auth_hmacsha512_init, crypto_auth_hmacsha512_state, 16 | crypto_auth_hmacsha512_update, crypto_auth_hmacsha512_verify, 17 | }; 18 | 19 | auth_module!( 20 | crypto_auth_hmacsha512, 21 | crypto_auth_hmacsha512_verify, 22 | crypto_auth_hmacsha512_KEYBYTES as usize, 23 | crypto_auth_hmacsha512_BYTES as usize 24 | ); 25 | 26 | auth_state!( 27 | crypto_auth_hmacsha512_state, 28 | crypto_auth_hmacsha512_init, 29 | crypto_auth_hmacsha512_update, 30 | crypto_auth_hmacsha512_final, 31 | crypto_auth_hmacsha512_BYTES 32 | ); 33 | 34 | #[cfg(test)] 35 | #[rustfmt::skip] 36 | mod test { 37 | use super::*; 38 | 39 | #[test] 40 | fn test_vector_1() { 41 | // corresponding to tests/auth.c from NaCl 42 | // "Test Case 2" from RFC 4231 43 | unwrap!(crate::init()); 44 | let key = Key([0x4a, 0x65, 0x66, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); 47 | let c = [0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, 0x79, 0x61, 0x20, 0x77, 0x61, 48 | 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 49 | 0x67, 0x3f]; 50 | 51 | let a_expected = [0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 52 | 0x3b, 0x56, 0xe0, 0xa3, 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 53 | 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, 0x97, 0x58, 0xbf, 0x75, 54 | 0xc0, 0x5a, 0x99, 0x4a, 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd, 55 | 0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b, 0x63, 0x6e, 0x07, 0x0a, 56 | 0x38, 0xbc, 0xe7, 0x37]; 57 | 58 | let Tag(a) = authenticate(&c, &key); 59 | assert!(a[..] == a_expected[..]); 60 | } 61 | 62 | #[test] 63 | fn test_vector_state_1() { 64 | // corresponding to tests/auth.c from NaCl 65 | // "Test Case 2" from RFC 4231 66 | unwrap!(crate::init()); 67 | let key = [0x4a, 0x65, 0x66, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 68 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 69 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 70 | let c = [0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, 0x79, 0x61, 0x20, 0x77, 0x61, 71 | 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 72 | 0x67, 0x3f]; 73 | 74 | let a_expected = [0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 75 | 0x3b, 0x56, 0xe0, 0xa3, 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 76 | 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, 0x97, 0x58, 0xbf, 0x75, 77 | 0xc0, 0x5a, 0x99, 0x4a, 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd, 78 | 0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b, 0x63, 0x6e, 0x07, 0x0a, 79 | 0x38, 0xbc, 0xe7, 0x37]; 80 | 81 | let mut state = State::init(&key); 82 | state.update(&c); 83 | let Tag(a) = state.finalize(); 84 | assert!(a[..] == a_expected[..]); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/crypto/auth/hmacsha512256.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! `HMAC-SHA-512-256`, i.e., the first 256 bits of 11 | //! `HMAC-SHA-512`. `HMAC-SHA-512-256` is conjectured to meet the standard notion 12 | //! of unforgeability. 13 | 14 | use crate::ffi::{ 15 | crypto_auth_hmacsha512256, crypto_auth_hmacsha512256_BYTES, crypto_auth_hmacsha512256_KEYBYTES, 16 | crypto_auth_hmacsha512256_final, crypto_auth_hmacsha512256_init, 17 | crypto_auth_hmacsha512256_state, crypto_auth_hmacsha512256_update, 18 | crypto_auth_hmacsha512256_verify, 19 | }; 20 | 21 | auth_module!( 22 | crypto_auth_hmacsha512256, 23 | crypto_auth_hmacsha512256_verify, 24 | crypto_auth_hmacsha512256_KEYBYTES as usize, 25 | crypto_auth_hmacsha512256_BYTES as usize 26 | ); 27 | 28 | auth_state!( 29 | crypto_auth_hmacsha512256_state, 30 | crypto_auth_hmacsha512256_init, 31 | crypto_auth_hmacsha512256_update, 32 | crypto_auth_hmacsha512256_final, 33 | crypto_auth_hmacsha512256_BYTES 34 | ); 35 | 36 | #[cfg(test)] 37 | #[rustfmt::skip] 38 | mod test { 39 | use super::*; 40 | 41 | #[test] 42 | fn test_vector_1() { 43 | // corresponding to tests/auth.c from NaCl 44 | // "Test Case 2" from RFC 4231 45 | unwrap!(crate::init()); 46 | let key = Key([74, 101, 102, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); 48 | let c = [0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, 0x79, 0x61, 0x20, 0x77, 0x61, 49 | 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 50 | 0x67, 0x3f]; 51 | 52 | let a_expected = [0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 53 | 0x3b, 0x56, 0xe0, 0xa3, 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 54 | 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54]; 55 | 56 | let Tag(a) = authenticate(&c, &key); 57 | assert!(a == a_expected); 58 | } 59 | 60 | #[test] 61 | fn test_vector_state_1() { 62 | // corresponding to tests/auth.c from NaCl 63 | // "Test Case 2" from RFC 4231 64 | unwrap!(crate::init()); 65 | let key = [74, 101, 102, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66 | 0, 0, 0, 0, 0, 0, 0, 0]; 67 | let c = [0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, 0x79, 0x61, 0x20, 0x77, 0x61, 68 | 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 69 | 0x67, 0x3f]; 70 | 71 | let a_expected = [0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 72 | 0x3b, 0x56, 0xe0, 0xa3, 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 73 | 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54]; 74 | 75 | let mut state = State::init(&key); 76 | state.update(&c); 77 | let Tag(a) = state.finalize(); 78 | assert!(a == a_expected); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/crypto/auth/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Secret-key authentication 11 | //! 12 | //! # Security model 13 | //! The `authenticate()` function, viewed as a function of the 14 | //! message for a uniform random key, is designed to meet the standard 15 | //! notion of unforgeability. This means that an attacker cannot find 16 | //! authenticators for any messages not authenticated by the sender, even if 17 | //! the attacker has adaptively influenced the messages authenticated by the 18 | //! sender. For a formal definition see, e.g., Section 2.4 of Bellare, 19 | //! Kilian, and Rogaway, "The security of the cipher block chaining message 20 | //! authentication code," Journal of Computer and System Sciences 61 (2000), 21 | //! 362–399; . 22 | //! 23 | //! `NaCl` does not make any promises regarding "strong" unforgeability; 24 | //! perhaps one valid authenticator can be converted into another valid 25 | //! authenticator for the same message. `NaCl` also does not make any promises 26 | //! regarding "truncated unforgeability." 27 | //! 28 | //! # Selected primitive 29 | //! `authenticate()` is currently an implementation of 30 | //! `HMAC-SHA-512-256`, i.e., the first 256 bits of `HMAC-SHA-512`. 31 | //! `HMAC-SHA-512-256` is conjectured to meet the standard notion of 32 | //! unforgeability. 33 | //! 34 | //! # Alternate primitives 35 | //! `NaCl` supports the following secret-key authentication functions: 36 | //! 37 | //! ----------------------------------------------------------------- 38 | //! |`crypto_auth` |primitive |BYTES|KEYBYTES| 39 | //! |----------------------------|-------------------|-----|--------| 40 | //! |`crypto_auth_hmacsha256` |`HMAC_SHA-256` |32 |32 | 41 | //! |`crypto_auth_hmacsha512256` |`HMAC_SHA-512-256` |32 |32 | 42 | //! |`crypto_auth_hmacsha512` |`HMAC_SHA-512` |64 |32 | 43 | //! ----------------------------------------------------------------- 44 | //! 45 | //! # Example (simple interface) 46 | //! ``` 47 | //! use rust_sodium::crypto::auth; 48 | //! 49 | //! let key = auth::gen_key(); 50 | //! let data_to_authenticate = b"some data"; 51 | //! let tag = auth::authenticate(data_to_authenticate, &key); 52 | //! assert!(auth::verify(&tag, data_to_authenticate, &key)); 53 | //! ``` 54 | //! 55 | //! # Example (streaming interface) 56 | //! ``` 57 | //! use rust_sodium::crypto::auth; 58 | //! use rust_sodium::randombytes; 59 | //! 60 | //! let key = randombytes::randombytes(123); 61 | //! 62 | //! let data_part_1 = b"some data"; 63 | //! let data_part_2 = b"some other data"; 64 | //! let mut state = auth::State::init(&key); 65 | //! state.update(data_part_1); 66 | //! state.update(data_part_2); 67 | //! let tag1 = state.finalize(); 68 | //! 69 | //! let data_2_part_1 = b"some datasome "; 70 | //! let data_2_part_2 = b"other data"; 71 | //! let mut state = auth::State::init(&key); 72 | //! state.update(data_2_part_1); 73 | //! state.update(data_2_part_2); 74 | //! let tag2 = state.finalize(); 75 | //! assert_eq!(tag1, tag2); 76 | //! ``` 77 | 78 | pub use self::hmacsha512256::*; 79 | #[macro_use] 80 | mod auth_macros; 81 | pub mod hmacsha256; 82 | pub mod hmacsha512; 83 | pub mod hmacsha512256; 84 | -------------------------------------------------------------------------------- /src/crypto/box_/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Public-key authenticated encryption 11 | //! 12 | //! # Security model 13 | //! The `seal()` function is designed to meet the standard notions of privacy and 14 | //! third-party unforgeability for a public-key authenticated-encryption scheme 15 | //! using nonces. For formal definitions see, e.g., Jee Hea An, "Authenticated 16 | //! encryption in the public-key setting: security notions and analyses," 17 | //! . 18 | //! 19 | //! Distinct messages between the same {sender, receiver} set are required 20 | //! to have distinct nonces. For example, the lexicographically smaller 21 | //! public key can use nonce 1 for its first message to the other key, nonce 22 | //! 3 for its second message, nonce 5 for its third message, etc., while the 23 | //! lexicographically larger public key uses nonce 2 for its first message 24 | //! to the other key, nonce 4 for its second message, nonce 6 for its third 25 | //! message, etc. Nonces are long enough that randomly generated nonces have 26 | //! negligible risk of collision. 27 | //! 28 | //! There is no harm in having the same nonce for different messages if the 29 | //! {sender, receiver} sets are different. This is true even if the sets 30 | //! overlap. For example, a sender can use the same nonce for two different 31 | //! messages if the messages are sent to two different public keys. 32 | //! 33 | //! The `seal()` function is not meant to provide non-repudiation. On the 34 | //! contrary: the `seal()` function guarantees repudiability. A receiver 35 | //! can freely modify a boxed message, and therefore cannot convince third 36 | //! parties that this particular message came from the sender. The sender 37 | //! and receiver are nevertheless protected against forgeries by other 38 | //! parties. In the terminology of 39 | //! , 40 | //! `crypto_box` uses "public-key authenticators" rather than "public-key 41 | //! signatures." 42 | //! 43 | //! Users who want public verifiability (or receiver-assisted public 44 | //! verifiability) should instead use signatures (or signcryption). 45 | //! Signature support is a high priority for `NaCl`; a signature API will be 46 | //! described in subsequent `NaCl` documentation. 47 | //! 48 | //! # Selected primitive 49 | //! `seal()` is `crypto_box_curve25519xsalsa20poly1305` , a particular 50 | //! combination of Curve25519, Salsa20, and Poly1305 specified in 51 | //! [Cryptography in `NaCl`](http://nacl.cr.yp.to/valid.html). 52 | //! 53 | //! This function is conjectured to meet the standard notions of privacy and 54 | //! third-party unforgeability. 55 | //! 56 | //! # Example (simple interface) 57 | //! ``` 58 | //! use rust_sodium::crypto::box_; 59 | //! 60 | //! let (ourpk, oursk) = box_::gen_keypair(); 61 | //! // normally theirpk is sent by the other party 62 | //! let (theirpk, theirsk) = box_::gen_keypair(); 63 | //! let nonce = box_::gen_nonce(); 64 | //! let plaintext = b"some data"; 65 | //! let ciphertext = box_::seal(plaintext, &nonce, &theirpk, &oursk); 66 | //! let their_plaintext = box_::open(&ciphertext, &nonce, &ourpk, &theirsk).unwrap(); 67 | //! assert!(plaintext == &their_plaintext[..]); 68 | //! ``` 69 | //! # Example (precomputation interface) 70 | //! ``` 71 | //! use rust_sodium::crypto::box_; 72 | //! 73 | //! let (ourpk, oursk) = box_::gen_keypair(); 74 | //! let (theirpk, theirsk) = box_::gen_keypair(); 75 | //! let our_precomputed_key = box_::precompute(&theirpk, &oursk); 76 | //! let nonce = box_::gen_nonce(); 77 | //! let plaintext = b"plaintext"; 78 | //! let ciphertext = box_::seal_precomputed(plaintext, &nonce, &our_precomputed_key); 79 | //! // this will be identical to our_precomputed_key 80 | //! let their_precomputed_key = box_::precompute(&ourpk, &theirsk); 81 | //! let their_plaintext = box_::open_precomputed(&ciphertext, &nonce, 82 | //! &their_precomputed_key).unwrap(); 83 | //! assert!(plaintext == &their_plaintext[..]); 84 | //! ``` 85 | 86 | pub use self::curve25519xsalsa20poly1305::*; 87 | pub mod curve25519xsalsa20poly1305; 88 | -------------------------------------------------------------------------------- /src/crypto/hash/hash_macros.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | macro_rules! hash_module (($hash_name:ident, 11 | $hash_state:ident, 12 | $hash_init:ident, 13 | $hash_update:ident, 14 | $hash_final:ident, 15 | $hashbytes:expr, 16 | $blockbytes:expr) => ( 17 | 18 | use std::mem; 19 | use libc::c_ulonglong; 20 | 21 | /// Number of bytes in a `Digest`. 22 | pub const DIGESTBYTES: usize = $hashbytes; 23 | 24 | /// Block size of the hash function. 25 | pub const BLOCKBYTES: usize = $blockbytes; 26 | 27 | new_type! { 28 | /// Digest-structure 29 | public Digest(DIGESTBYTES); 30 | } 31 | 32 | /// `hash` hashes a message `m`. It returns a hash `h`. 33 | pub fn hash(m: &[u8]) -> Digest { 34 | unsafe { 35 | let mut h = [0; DIGESTBYTES]; 36 | let _todo_use_result = $hash_name(h.as_mut_ptr(), m.as_ptr(), m.len() as c_ulonglong); 37 | Digest(h) 38 | } 39 | } 40 | 41 | /// `State` contains the state for multi-part (streaming) hash computations. This allows the caller 42 | /// to process a message as a sequence of multiple chunks. 43 | pub struct State($hash_state); 44 | 45 | impl State { 46 | /// `new` constructs and initializes a new `State`. 47 | pub fn new() -> Self { 48 | unsafe { 49 | let mut st: $hash_state = mem::uninitialized(); 50 | let _ = $hash_init(&mut st); 51 | State(st) 52 | } 53 | } 54 | 55 | /// `update` updates the `State` with `data`. `update` can be called multiple times in order 56 | /// to compute the hash from sequential chunks of the message. 57 | pub fn update(&mut self, data: &[u8]) { 58 | unsafe { 59 | let _ = $hash_update(&mut self.0, data.as_ptr(), data.len() as c_ulonglong); 60 | } 61 | } 62 | 63 | /// `finalize` finalizes the state and returns the digest value. `finalize` consumes the 64 | /// `State` so that it cannot be accidentally reused. 65 | pub fn finalize(mut self) -> Digest { 66 | unsafe { 67 | let mut digest = [0u8; DIGESTBYTES]; 68 | let _ = $hash_final(&mut self.0, digest.as_mut_ptr()); 69 | Digest(digest) 70 | } 71 | } 72 | } 73 | 74 | impl Default for State { 75 | fn default() -> State { 76 | State::new() 77 | } 78 | } 79 | 80 | #[cfg(test)] 81 | mod test_m { 82 | use super::*; 83 | 84 | #[test] 85 | fn test_hash_multipart() { 86 | use crate::randombytes::randombytes; 87 | unwrap!(crate::init()); 88 | for i in 0..256usize { 89 | let m = randombytes(i); 90 | let h = hash(&m); 91 | let mut state = State::new(); 92 | for b in m.chunks(3) { 93 | state.update(b); 94 | } 95 | let h2 = state.finalize(); 96 | assert_eq!(h, h2); 97 | } 98 | } 99 | } 100 | 101 | #[cfg(test)] 102 | mod test_encode { 103 | use super::*; 104 | use crate::test_utils::round_trip; 105 | 106 | #[test] 107 | fn test_serialisation() { 108 | use crate::randombytes::randombytes; 109 | unwrap!(crate::init()); 110 | for i in 0..32usize { 111 | let m = randombytes(i); 112 | let d = hash(&m[..]); 113 | round_trip(&d); 114 | } 115 | } 116 | } 117 | 118 | #[cfg(feature = "benchmarks")] 119 | #[cfg(test)] 120 | mod bench_m { 121 | extern crate test; 122 | use crate::randombytes::randombytes; 123 | use super::*; 124 | 125 | const BENCH_SIZES: [usize; 14] = [0, 1, 2, 4, 8, 16, 32, 64, 126 | 128, 256, 512, 1024, 2048, 4096]; 127 | 128 | #[bench] 129 | fn bench_hash(b: &mut test::Bencher) { 130 | unwrap!(crate::init()); 131 | let ms: Vec> = BENCH_SIZES.iter().map(|s| { 132 | randombytes(*s) 133 | }).collect(); 134 | b.iter(|| { 135 | for m in ms.iter() { 136 | hash(&m); 137 | } 138 | }); 139 | } 140 | } 141 | 142 | )); 143 | -------------------------------------------------------------------------------- /src/crypto/hash/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Hashing 11 | //! 12 | //! # Security model 13 | //! The `hash()` function is designed to be usable as a strong 14 | //! component of DSA, RSA-PSS, key derivation, hash-based 15 | //! message-authentication codes, hash-based ciphers, and various other 16 | //! common applications. "Strong" means that the security of these 17 | //! applications, when instantiated with `hash()`, is the same 18 | //! as the security of the applications against generic attacks. In 19 | //! particular, the `hash()` function is designed to make 20 | //! finding collisions difficult. 21 | //! 22 | //! # Selected primitive 23 | //! `hash()` is currently an implementation of `SHA-512`. 24 | //! 25 | //! There has been considerable degradation of public confidence in the 26 | //! security conjectures for many hash functions, including `SHA-512`. 27 | //! However, for the moment, there do not appear to be alternatives that 28 | //! inspire satisfactory levels of confidence. One can hope that NIST's 29 | //! SHA-3 competition will improve the situation. 30 | //! 31 | //! # Alternate primitives 32 | //! `NaCl` supports the following hash functions: 33 | //! 34 | //! ----------------------------------------- 35 | //! |`crypto_hash` |primitive |BYTES | 36 | //! |---------------------|----------|------| 37 | //! |`crypto_hash_sha256` |`SHA-256` |32 | 38 | //! |`crypto_hash_sha512` |`SHA-512` |64 | 39 | //! ----------------------------------------- 40 | //! 41 | //! # Example 42 | //! ``` 43 | //! # #![allow(unused_variables)] 44 | //! use rust_sodium::crypto::hash; 45 | //! 46 | //! let data_to_hash = b"some data"; 47 | //! let digest = hash::hash(data_to_hash); 48 | //! 49 | //! let mut hash_state = hash::State::new(); 50 | //! hash_state.update(b"some "); 51 | //! hash_state.update(b"data!"); 52 | //! let digest = hash_state.finalize(); 53 | //! ``` 54 | 55 | pub use self::sha512::*; 56 | #[macro_use] 57 | mod hash_macros; 58 | pub mod sha256; 59 | pub mod sha512; 60 | -------------------------------------------------------------------------------- /src/crypto/hash/sha256.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! `SHA-256`. 11 | //! 12 | //! There has been considerable degradation of public confidence in the 13 | //! security conjectures for many hash functions, including `SHA-256`. 14 | //! However, for the moment, there do not appear to be alternatives that 15 | //! inspire satisfactory levels of confidence. One can hope that NIST's 16 | //! SHA-3 competition will improve the situation. 17 | 18 | use crate::ffi::{ 19 | crypto_hash_sha256, crypto_hash_sha256_BYTES, crypto_hash_sha256_final, 20 | crypto_hash_sha256_init, crypto_hash_sha256_state, crypto_hash_sha256_update, 21 | }; 22 | 23 | hash_module!( 24 | crypto_hash_sha256, 25 | crypto_hash_sha256_state, 26 | crypto_hash_sha256_init, 27 | crypto_hash_sha256_update, 28 | crypto_hash_sha256_final, 29 | crypto_hash_sha256_BYTES as usize, 30 | 64 31 | ); 32 | 33 | #[cfg(test)] 34 | mod test { 35 | use super::*; 36 | 37 | #[test] 38 | #[rustfmt::skip] 39 | fn test_vector_1() { 40 | // hash of empty string 41 | unwrap!(crate::init()); 42 | let x = []; 43 | let h_expected = [0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 44 | 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 45 | 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55]; 46 | let Digest(h) = hash(&x); 47 | assert!(h == h_expected); 48 | } 49 | 50 | #[test] 51 | #[rustfmt::skip] 52 | fn test_vector_2() { 53 | // The quick brown fox jumps over the lazy dog 54 | unwrap!(crate::init()); 55 | let x = [0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x20, 0x62, 0x72, 0x6f, 56 | 0x77, 0x6e, 0x20, 0x66, 0x6f, 0x78, 0x20, 0x6a, 0x75, 0x6d, 0x70, 0x73, 0x20, 57 | 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x7a, 0x79, 58 | 0x20, 0x64, 0x6f, 0x67]; 59 | let h_expected = [0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94, 0x69, 0xca, 0x9a, 0xbc, 60 | 0xb0, 0x08, 0x2e, 0x4f, 0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76, 61 | 0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92]; 62 | let Digest(h) = hash(&x); 63 | assert!(h == h_expected); 64 | } 65 | 66 | fn test_nist_vector(filename: &str) { 67 | use hex; 68 | use std::fs::File; 69 | use std::io::{BufRead, BufReader}; 70 | 71 | unwrap!(crate::init()); 72 | let mut r = BufReader::new(unwrap!(File::open(filename))); 73 | let mut line = String::new(); 74 | loop { 75 | line.clear(); 76 | let _ = unwrap!(r.read_line(&mut line)); 77 | if line.is_empty() { 78 | break; 79 | } 80 | let starts_with_len = line.starts_with("Len = "); 81 | if starts_with_len { 82 | let len: usize = unwrap!(line[6..].trim().parse()); 83 | line.clear(); 84 | let _ = unwrap!(r.read_line(&mut line)); 85 | let rawmsg = unwrap!(hex::decode(line[6..].trim())); 86 | let msg = &rawmsg[..len / 8]; 87 | line.clear(); 88 | let _ = unwrap!(r.read_line(&mut line)); 89 | let md = unwrap!(hex::decode(line[5..].trim())); 90 | let Digest(digest) = hash(msg); 91 | assert!(digest[..] == md[..]); 92 | } 93 | } 94 | } 95 | 96 | #[test] 97 | fn test_vectors_nist_short() { 98 | test_nist_vector("testvectors/SHA256ShortMsg.rsp"); 99 | } 100 | 101 | #[test] 102 | fn test_vectors_nist_long() { 103 | test_nist_vector("testvectors/SHA256LongMsg.rsp"); 104 | } 105 | 106 | #[test] 107 | #[rustfmt::skip] 108 | fn test_hash_state_empty() { 109 | // hash of empty string 110 | unwrap!(crate::init()); 111 | let h_expected = [0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 112 | 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 113 | 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55]; 114 | let hash_state = State::new(); 115 | let Digest(h) = hash_state.finalize(); 116 | assert!(h == h_expected); 117 | } 118 | 119 | #[test] 120 | #[rustfmt::skip] 121 | fn test_hash_state_multi_parts() { 122 | // The quick brown fox jumps over the lazy dog 123 | unwrap!(crate::init()); 124 | let x = [0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x20, 0x62, 0x72, 0x6f, 125 | 0x77, 0x6e, 0x20, 0x66, 0x6f, 0x78, 0x20, 0x6a, 0x75, 0x6d, 0x70, 0x73, 0x20, 0x6f, 126 | 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x7a, 0x79, 0x20, 0x64, 127 | 0x6f, 0x67]; 128 | let h_expected = [0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94, 0x69, 0xca, 0x9a, 0xbc, 129 | 0xb0, 0x08, 0x2e, 0x4f, 0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76, 0x2d, 0x02, 130 | 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92]; 131 | let mut hash_state = State::new(); 132 | for chunk in x.chunks(3) { 133 | hash_state.update(chunk); 134 | } 135 | let Digest(h) = hash_state.finalize(); 136 | assert!(h == h_expected); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/crypto/hash/sha512.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! `SHA-512`. 11 | //! 12 | //! There has been considerable degradation of public confidence in the 13 | //! security conjectures for many hash functions, including `SHA-512`. 14 | //! However, for the moment, there do not appear to be alternatives that 15 | //! inspire satisfactory levels of confidence. One can hope that NIST's 16 | //! SHA-3 competition will improve the situation. 17 | 18 | use crate::ffi::{ 19 | crypto_hash_sha512, crypto_hash_sha512_BYTES, crypto_hash_sha512_final, 20 | crypto_hash_sha512_init, crypto_hash_sha512_state, crypto_hash_sha512_update, 21 | }; 22 | 23 | hash_module!( 24 | crypto_hash_sha512, 25 | crypto_hash_sha512_state, 26 | crypto_hash_sha512_init, 27 | crypto_hash_sha512_update, 28 | crypto_hash_sha512_final, 29 | crypto_hash_sha512_BYTES as usize, 30 | 128 31 | ); 32 | 33 | #[cfg(test)] 34 | mod test { 35 | use super::*; 36 | 37 | #[test] 38 | #[rustfmt::skip] 39 | fn test_vector_1() { 40 | // corresponding to tests/hash.c, tests/hash2.cpp, 41 | // tests/hash3.c and tests/hash4.cpp from NaCl 42 | unwrap!(crate::init()); 43 | let x = [0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0xa]; 44 | let h_expected = [0x24, 0xf9, 0x50, 0xaa, 0xc7, 0xb9, 0xea, 0x9b, 0x3c, 0xb7, 0x28, 0x22, 45 | 0x8a, 0x0c, 0x82, 0xb6, 0x7c, 0x39, 0xe9, 0x6b, 0x4b, 0x34, 0x47, 0x98, 46 | 0x87, 0x0d, 0x5d, 0xae, 0xe9, 0x3e, 0x3a, 0xe5, 0x93, 0x1b, 0xaa, 0xe8, 47 | 0xc7, 0xca, 0xcf, 0xea, 0x4b, 0x62, 0x94, 0x52, 0xc3, 0x80, 0x26, 0xa8, 48 | 0x1d, 0x13, 0x8b, 0xc7, 0xaa, 0xd1, 0xaf, 0x3e, 0xf7, 0xbf, 0xd5, 0xec, 49 | 0x64, 0x6d, 0x6c, 0x28]; 50 | let Digest(h) = hash(&x); 51 | assert!(h[..] == h_expected[..]); 52 | } 53 | 54 | fn test_nist_vector(filename: &str) { 55 | use hex; 56 | use std::fs::File; 57 | use std::io::{BufRead, BufReader}; 58 | 59 | unwrap!(crate::init()); 60 | let mut r = BufReader::new(unwrap!(File::open(filename))); 61 | let mut line = String::new(); 62 | loop { 63 | line.clear(); 64 | let _ = unwrap!(r.read_line(&mut line)); 65 | if line.is_empty() { 66 | break; 67 | } 68 | let starts_with_len = line.starts_with("Len = "); 69 | if starts_with_len { 70 | let len: usize = unwrap!(line[6..].trim().parse()); 71 | line.clear(); 72 | let _ = unwrap!(r.read_line(&mut line)); 73 | let rawmsg = unwrap!(hex::decode(line[6..].trim())); 74 | let msg = &rawmsg[..len / 8]; 75 | line.clear(); 76 | let _ = unwrap!(r.read_line(&mut line)); 77 | let md = unwrap!(hex::decode(line[5..].trim())); 78 | let Digest(digest) = hash(msg); 79 | assert!(digest[..] == md[..]); 80 | } 81 | } 82 | } 83 | 84 | #[test] 85 | fn test_vectors_nist_short() { 86 | test_nist_vector("testvectors/SHA512ShortMsg.rsp"); 87 | } 88 | 89 | #[test] 90 | fn test_vectors_nist_long() { 91 | test_nist_vector("testvectors/SHA512LongMsg.rsp"); 92 | } 93 | 94 | #[test] 95 | #[rustfmt::skip] 96 | fn test_hash_state_multi_parts() { 97 | // corresponding to tests/hash.c, tests/hash2.cpp, 98 | // tests/hash3.c and tests/hash4.cpp from NaCl 99 | unwrap!(crate::init()); 100 | let x = [0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0xa]; 101 | let h_expected = [0x24, 0xf9, 0x50, 0xaa, 0xc7, 0xb9, 0xea, 0x9b, 0x3c, 0xb7, 0x28, 0x22, 102 | 0x8a, 0x0c, 0x82, 0xb6, 0x7c, 0x39, 0xe9, 0x6b, 0x4b, 0x34, 0x47, 0x98, 0x87, 0x0d, 103 | 0x5d, 0xae, 0xe9, 0x3e, 0x3a, 0xe5, 0x93, 0x1b, 0xaa, 0xe8, 0xc7, 0xca, 0xcf, 0xea, 104 | 0x4b, 0x62, 0x94, 0x52, 0xc3, 0x80, 0x26, 0xa8, 0x1d, 0x13, 0x8b, 0xc7, 0xaa, 0xd1, 105 | 0xaf, 0x3e, 0xf7, 0xbf, 0xd5, 0xec, 0x64, 0x6d, 0x6c, 0x28]; 106 | let mut hash_state = State::new(); 107 | for chunk in x.chunks(3) { 108 | hash_state.update(chunk); 109 | } 110 | let Digest(h) = hash_state.finalize(); 111 | assert!(h[..] == h_expected[..]); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/crypto/kx/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Key exchange 11 | //! 12 | //! Using the key exchange API, two parties can securely compute a set of shared keys using their 13 | //! peer's public key and their own secret key. 14 | //! 15 | //! This API was introduced in libsodium 1.0.12. 16 | //! 17 | //! # Example 18 | //! 19 | //! ``` 20 | //! use rust_sodium::crypto::kx; 21 | //! 22 | //! // client-side 23 | //! let (client_pk, client_sk) = kx::gen_keypair(); 24 | //! 25 | //! // server-side 26 | //! let (server_pk, server_sk) = kx::gen_keypair(); 27 | //! 28 | //! // client and server exchanges client_pk and server_pk 29 | //! 30 | //! // client deduces the two session keys rx1 and tx1 31 | //! let (rx1, tx1) = match kx::client_session_keys(&client_pk, &client_sk, &server_pk) { 32 | //! Ok((rx, tx)) => (rx, tx), 33 | //! Err(()) => panic!("bad server signature"), 34 | //! }; 35 | //! 36 | //! // server performs the same operation 37 | //! let (rx2, tx2) = match kx::server_session_keys(&server_pk, &server_sk, &client_pk) { 38 | //! Ok((rx, tx)) => (rx, tx), 39 | //! Err(()) => panic!("bad client signature"), 40 | //! }; 41 | //! 42 | //! assert!(rx1==tx2); 43 | //! assert!(rx2==tx1); 44 | //! 45 | //! ``` 46 | 47 | pub use self::x25519blake2b::*; 48 | pub mod x25519blake2b; 49 | -------------------------------------------------------------------------------- /src/crypto/kx/x25519blake2b.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! `x25519blake2b` is the current default key exchange scheme of `libsodium`. 11 | 12 | use crate::ffi; 13 | 14 | /// Number of bytes in a `PublicKey`. 15 | pub const PUBLICKEYBYTES: usize = ffi::crypto_kx_PUBLICKEYBYTES as usize; 16 | 17 | /// Number of bytes in a `SecretKey`. 18 | pub const SECRETKEYBYTES: usize = ffi::crypto_kx_SECRETKEYBYTES as usize; 19 | 20 | /// Number of bytes in a `Seed`. 21 | pub const SEEDBYTES: usize = ffi::crypto_kx_SEEDBYTES as usize; 22 | 23 | /// Number of bytes in a `SessionKey`. 24 | pub const SESSIONKEYBYTES: usize = ffi::crypto_kx_SESSIONKEYBYTES as usize; 25 | 26 | new_type! { 27 | /// `PublicKey` for key exchanges. 28 | public PublicKey(PUBLICKEYBYTES); 29 | } 30 | 31 | new_type! { 32 | /// `SecretKey` for key exchanges. 33 | /// 34 | /// When a `SecretKey` goes out of scope its contents will be zeroed out 35 | secret SecretKey(SECRETKEYBYTES); 36 | } 37 | 38 | new_type! { 39 | /// `Seed` that can be used for keypair generation 40 | /// 41 | /// The `Seed` is used by `keypair_from_seed()` to generate a secret and 42 | /// public signature key. 43 | /// 44 | /// When a `Seed` goes out of scope its content will be zeroed out 45 | secret Seed(SEEDBYTES); 46 | } 47 | 48 | new_type! { 49 | /// `SessionKey` is returned by `client_session_keys` and `server_session_keys` and is the 50 | /// exchanged secret between the client and server. 51 | secret SessionKey(SESSIONKEYBYTES); 52 | } 53 | 54 | /// `gen_keypair()` randomly generates a secret key and a corresponding public 55 | /// key. 56 | /// 57 | /// THREAD SAFETY: `gen_keypair()` is thread-safe provided that you have 58 | /// called `rust_sodium::init()` once before using any other function 59 | /// from `rust_sodium`. 60 | pub fn gen_keypair() -> (PublicKey, SecretKey) { 61 | unsafe { 62 | let mut pk = [0u8; PUBLICKEYBYTES]; 63 | let mut sk = [0u8; SECRETKEYBYTES]; 64 | let _ = ffi::crypto_kx_keypair(pk.as_mut_ptr(), sk.as_mut_ptr()); 65 | (PublicKey(pk), SecretKey(sk)) 66 | } 67 | } 68 | 69 | /// `keypair_from_seed()` computes a secret key and a corresponding public key 70 | /// from a `Seed`. 71 | pub fn keypair_from_seed(&Seed(ref seed): &Seed) -> (PublicKey, SecretKey) { 72 | unsafe { 73 | let mut pk = [0u8; PUBLICKEYBYTES]; 74 | let mut sk = [0u8; SECRETKEYBYTES]; 75 | let _ = ffi::crypto_kx_seed_keypair(pk.as_mut_ptr(), sk.as_mut_ptr(), seed.as_ptr()); 76 | (PublicKey(pk), SecretKey(sk)) 77 | } 78 | } 79 | 80 | /// `server_session_keys()` computes a pair of shared keys (rx and tx) using the server's public 81 | /// key `server_pk`, the server's secret key `server_sk` and the client's public key `client_pk`. 82 | /// If the client's public key is acceptable, it returns the two shared keys, the first for `rx` 83 | /// and the second for `tx`. Otherwise, it returns `None`. 84 | pub fn server_session_keys( 85 | &PublicKey(ref server_pk): &PublicKey, 86 | &SecretKey(ref server_sk): &SecretKey, 87 | &PublicKey(ref client_pk): &PublicKey, 88 | ) -> Result<(SessionKey, SessionKey), ()> { 89 | unsafe { 90 | let mut rx = [0u8; SESSIONKEYBYTES]; 91 | let mut tx = [0u8; SESSIONKEYBYTES]; 92 | let r = ffi::crypto_kx_server_session_keys( 93 | rx.as_mut_ptr(), 94 | tx.as_mut_ptr(), 95 | server_pk.as_ptr(), 96 | server_sk.as_ptr(), 97 | client_pk.as_ptr(), 98 | ); 99 | 100 | if r != 0 { 101 | Err(()) 102 | } else { 103 | Ok((SessionKey(rx), SessionKey(tx))) 104 | } 105 | } 106 | } 107 | 108 | /// `client_session_keys()` computes a pair of shared keys (rx and tx) using the client's public 109 | /// key `client_pk`, the client's secret key `client_sk` and the server's public key `server_pk`. 110 | /// If the server's public key is acceptable, it returns the two shared keys, the first for `rx` 111 | /// and the second for `tx`. Otherwise, it returns `None`. 112 | pub fn client_session_keys( 113 | &PublicKey(ref client_pk): &PublicKey, 114 | &SecretKey(ref client_sk): &SecretKey, 115 | &PublicKey(ref server_pk): &PublicKey, 116 | ) -> Result<(SessionKey, SessionKey), ()> { 117 | unsafe { 118 | let mut rx = [0u8; SESSIONKEYBYTES]; 119 | let mut tx = [0u8; SESSIONKEYBYTES]; 120 | let r = ffi::crypto_kx_client_session_keys( 121 | rx.as_mut_ptr(), 122 | tx.as_mut_ptr(), 123 | client_pk.as_ptr(), 124 | client_sk.as_ptr(), 125 | server_pk.as_ptr(), 126 | ); 127 | 128 | if r != 0 { 129 | Err(()) 130 | } else { 131 | Ok((SessionKey(rx), SessionKey(tx))) 132 | } 133 | } 134 | } 135 | 136 | #[cfg(test)] 137 | mod test { 138 | use super::*; 139 | 140 | #[test] 141 | fn test_kx() { 142 | unwrap!(crate::init()); 143 | let (client_pk, client_sk) = gen_keypair(); 144 | let (server_pk, server_sk) = gen_keypair(); 145 | 146 | assert!(client_pk != server_pk); 147 | assert!(client_sk != server_sk); 148 | 149 | let (client_rx, client_tx) = 150 | unwrap!(client_session_keys(&client_pk, &client_sk, &server_pk)); 151 | let (server_rx, server_tx) = 152 | unwrap!(server_session_keys(&server_pk, &server_sk, &client_pk)); 153 | 154 | assert!(client_rx == server_tx); 155 | assert!(client_tx == server_rx); 156 | } 157 | 158 | #[test] 159 | fn test_kx_non_acceptable_keys() { 160 | unwrap!(crate::init()); 161 | let (client_pk, client_sk) = gen_keypair(); 162 | let (server_pk, server_sk) = gen_keypair(); 163 | 164 | // non correct public keys 165 | let fake_client_pk = PublicKey([0u8; PUBLICKEYBYTES]); 166 | let fake_server_pk = PublicKey([0u8; PUBLICKEYBYTES]); 167 | 168 | assert!(client_session_keys(&client_pk, &client_sk, &fake_server_pk) == Err(())); 169 | assert!(server_session_keys(&server_pk, &server_sk, &fake_client_pk) == Err(())); 170 | } 171 | 172 | #[test] 173 | #[rustfmt::skip] 174 | fn test_vectors() { 175 | unwrap!(crate::init()); 176 | let small_order_p = PublicKey([ 177 | 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 178 | 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 179 | 0x5f, 0x49, 0xb8, 0x00]); 180 | 181 | let mut seed = [0u8; SEEDBYTES]; 182 | for (i, elt) in seed.iter_mut().enumerate() { 183 | *elt = i as u8; 184 | } 185 | let mut seed = Seed(seed); 186 | let (mut client_pk, client_sk) = keypair_from_seed(&seed); 187 | 188 | let client_pk_expected = PublicKey([ 189 | 0x0e, 0x02, 0x16, 0x22, 0x3f, 0x14, 0x71, 0x43, 0xd3, 0x26, 0x15, 0xa9, 0x11, 0x89, 190 | 0xc2, 0x88, 0xc1, 0x72, 0x8c, 0xba, 0x3c, 0xc5, 0xf9, 0xf6, 0x21, 0xb1, 0x02, 0x6e, 191 | 0x03, 0xd8, 0x31, 0x29]); 192 | assert_eq!(client_pk, client_pk_expected); 193 | let client_sk_expected = SecretKey([ 194 | 0xcb, 0x2f, 0x51, 0x60, 0xfc, 0x1f, 0x7e, 0x05, 0xa5, 0x5e, 0xf4, 0x9d, 0x34, 0x0b, 195 | 0x48, 0xda, 0x2e, 0x5a, 0x78, 0x09, 0x9d, 0x53, 0x39, 0x33, 0x51, 0xcd, 0x57, 0x9d, 196 | 0xd4, 0x25, 0x03, 0xd6]); 197 | assert_eq!(client_sk, client_sk_expected); 198 | 199 | let (server_pk, server_sk) = gen_keypair(); 200 | 201 | assert_eq!( 202 | client_session_keys(&client_pk, &client_sk, &small_order_p), 203 | Err(()) 204 | ); 205 | let (client_rx, client_tx) = unwrap!(client_session_keys(&client_pk, &client_sk, &server_pk) 206 | ); 207 | 208 | assert_eq!( 209 | server_session_keys(&server_pk, &server_sk, &small_order_p), 210 | Err(()) 211 | ); 212 | let _ = unwrap!(server_session_keys(&server_pk, &server_sk, &client_pk)); 213 | 214 | client_pk.0[0] += 1; 215 | 216 | let (server_rx, server_tx) = unwrap!(server_session_keys(&server_pk, &server_sk, &client_pk)); 217 | 218 | assert_ne!(server_rx.0, client_tx.0); 219 | assert_ne!(server_tx.0, client_rx.0); 220 | 221 | let (client_pk, _) = gen_keypair(); 222 | let (server_rx, server_tx) = unwrap!(server_session_keys(&server_pk, &server_sk, &client_pk)); 223 | 224 | assert_ne!(server_rx.0, client_tx.0); 225 | assert_ne!(server_tx.0, client_rx.0); 226 | 227 | let (client_pk, client_sk) = keypair_from_seed(&seed); 228 | seed.0[0] += 1; 229 | let (server_pk, server_sk) = keypair_from_seed(&seed); 230 | 231 | let (server_rx, server_tx) = unwrap!(server_session_keys(&server_pk, &server_sk, &client_pk)); 232 | let server_rx_expected = SessionKey([ 233 | 0x62, 0xc8, 0xf4, 0xfa, 0x81, 0x80, 0x0a, 0xbd, 0x05, 0x77, 0xd9, 0x99, 0x18, 0xd1, 234 | 0x29, 0xb6, 0x5d, 0xeb, 0x78, 0x9a, 0xf8, 0xc8, 0x35, 0x1f, 0x39, 0x1f, 0xeb, 0x0c, 235 | 0xbf, 0x23, 0x86, 0x04]); 236 | let server_tx_expected = SessionKey([ 237 | 0x74, 0x95, 0x19, 0xc6, 0x80, 0x59, 0xbc, 0xe6, 0x9f, 0x7c, 0xfc, 0xc7, 0xb3, 0x87, 238 | 0xa3, 0xde, 0x1a, 0x1e, 0x82, 0x37, 0xd1, 0x10, 0x99, 0x13, 0x23, 0xbf, 0x62, 0x87, 239 | 0x01, 0x15, 0x73, 0x1a]); 240 | assert_eq!(server_rx, server_rx_expected); 241 | assert_eq!(server_tx, server_tx_expected); 242 | 243 | let (client_rx, client_tx) = unwrap!(client_session_keys(&client_pk, &client_sk, &server_pk)); 244 | let client_rx_expected = SessionKey([ 245 | 0x74, 0x95, 0x19, 0xc6, 0x80, 0x59, 0xbc, 0xe6, 0x9f, 0x7c, 0xfc, 0xc7, 0xb3, 0x87, 246 | 0xa3, 0xde, 0x1a, 0x1e, 0x82, 0x37, 0xd1, 0x10, 0x99, 0x13, 0x23, 0xbf, 0x62, 0x87, 247 | 0x01, 0x15, 0x73, 0x1a]); 248 | let client_tx_expected = SessionKey([ 249 | 0x62, 0xc8, 0xf4, 0xfa, 0x81, 0x80, 0x0a, 0xbd, 0x05, 0x77, 0xd9, 0x99, 0x18, 0xd1, 250 | 0x29, 0xb6, 0x5d, 0xeb, 0x78, 0x9a, 0xf8, 0xc8, 0x35, 0x1f, 0x39, 0x1f, 0xeb, 0x0c, 251 | 0xbf, 0x23, 0x86, 0x04]); 252 | assert_eq!(client_rx, client_rx_expected); 253 | assert_eq!(client_tx, client_tx_expected); 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /src/crypto/onetimeauth/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Secret-key One-time authentication 11 | //! 12 | //! # Security model 13 | //! The `authenticate()` function, viewed as a function 14 | //! of the message for a uniform random key, is designed to meet the 15 | //! standard notion of unforgeability after a single message. After the 16 | //! sender authenticates one message, an attacker cannot find authenticators 17 | //! for any other messages. 18 | //! 19 | //! The sender must not use `authenticate()` to authenticate more than one message 20 | //! under the same key. Authenticators for two messages under the same key should 21 | //! be expected to reveal enough information to allow forgeries of authenticators 22 | //! on other messages. 23 | //! 24 | //! # Selected primitive 25 | //! `authenticate()` is `crypto_onetimeauth_poly1305`, an authenticator specified 26 | //! in [Cryptography in `NaCl`](http://nacl.cr.yp.to/valid.html), Section 9. This 27 | //! authenticator is proven to meet the standard notion of unforgeability after a 28 | //! single message. 29 | //! 30 | //! # Example 31 | //! ``` 32 | //! use rust_sodium::crypto::onetimeauth; 33 | //! 34 | //! let key = onetimeauth::gen_key(); 35 | //! let data_to_authenticate = b"some data"; 36 | //! let tag = onetimeauth::authenticate(data_to_authenticate, &key); 37 | //! assert!(onetimeauth::verify(&tag, data_to_authenticate, &key)); 38 | //! ``` 39 | 40 | pub use self::poly1305::*; 41 | #[path = "../auth/auth_macros.rs"] 42 | #[macro_use] 43 | mod auth_macros; 44 | pub mod poly1305; 45 | -------------------------------------------------------------------------------- /src/crypto/onetimeauth/poly1305.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! `crypto_onetimeauth_poly1305`, an authenticator specified 11 | //! in [Cryptography in `NaCl`](http://nacl.cr.yp.to/valid.html), Section 9. This 12 | //! authenticator is proven to meet the standard notion of unforgeability after a 13 | //! single message. 14 | 15 | use crate::ffi::{ 16 | crypto_onetimeauth_poly1305, crypto_onetimeauth_poly1305_BYTES, 17 | crypto_onetimeauth_poly1305_KEYBYTES, crypto_onetimeauth_poly1305_verify, 18 | }; 19 | 20 | auth_module!( 21 | crypto_onetimeauth_poly1305, 22 | crypto_onetimeauth_poly1305_verify, 23 | crypto_onetimeauth_poly1305_KEYBYTES as usize, 24 | crypto_onetimeauth_poly1305_BYTES as usize 25 | ); 26 | 27 | #[cfg(test)] 28 | mod test { 29 | use super::*; 30 | 31 | #[test] 32 | #[rustfmt::skip] 33 | fn test_vector_1() { 34 | // corresponding to tests/onetimeauth.c, tests/onetimeauth2.c, 35 | // tests/onetimeauth5.cpp and tests/onetimeauth6.cpp from NaCl 36 | unwrap!(crate::init()); 37 | let key = Key([0xee, 0xa6, 0xa7, 0x25, 0x1c, 0x1e, 0x72, 0x91, 0x6d, 0x11, 0xc2, 0xcb, 38 | 0x21, 0x4d, 0x3c, 0x25, 0x25, 0x39, 0x12, 0x1d, 0x8e, 0x23, 0x4e, 0x65, 39 | 0x2d, 0x65, 0x1f, 0xa4, 0xc8, 0xcf, 0xf8, 0x80]); 40 | 41 | let c = [0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73, 0xc2, 0x96, 0x50, 0xba, 0x32, 42 | 0xfc, 0x76, 0xce, 0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4, 0x47, 0x6f, 43 | 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a, 0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 44 | 0x7b, 0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72, 0x71, 0xd2, 0xc2, 0x0f, 45 | 0x9b, 0x92, 0x8f, 0xe2, 0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38, 0xb4, 46 | 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a, 0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 47 | 0x26, 0xae, 0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea, 0xbd, 0x6b, 0xb3, 48 | 0x73, 0x2b, 0xc0, 0xe9, 0xda, 0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde, 49 | 0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3, 0x79, 0x73, 0xf6, 0x22, 0xa4, 50 | 0x3d, 0x14, 0xa6, 0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74, 0xe3, 0x55, 51 | 0xa5]; 52 | 53 | let a_expected = Tag([0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5, 0x2a, 0x7d, 0xfb, 54 | 0x4b, 0x3d, 0x33, 0x05, 0xd9]); 55 | let a = authenticate(&c, &key); 56 | assert!(a == a_expected); 57 | assert!(verify(&a, &c, &key)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/crypto/pwhash/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Password Hashing 11 | //! 12 | //! Secret keys used to encrypt or sign confidential data have to be chosen from 13 | //! a very large keyspace. However, passwords are usually short, human-generated 14 | //! strings, making dictionary attacks practical. 15 | //! 16 | //! The pwhash operation derives a secret key of any size from a password and a 17 | //! salt. 18 | //! 19 | //! - The generated key has the size defined by the application, no matter what 20 | //! the password length is. 21 | //! - The same password hashed with same parameters will 22 | //! always produce the same key. 23 | //! - The same password hashed with different salts 24 | //! will produce different keys. 25 | //! - The function deriving a key from a password 26 | //! and a salt is CPU intensive and intentionally requires a fair amount of 27 | //! memory. Therefore, it mitigates brute-force attacks by requiring a 28 | //! significant effort to verify each password. 29 | //! 30 | //! Common use cases: 31 | //! 32 | //! - Protecting an on-disk secret key with a password, 33 | //! - Password storage, or rather: storing what it takes to verify a password 34 | //! without having to store the actual password. 35 | //! 36 | //! # Example (key derivation) 37 | //! ``` 38 | //! use rust_sodium::crypto::secretbox; 39 | //! use rust_sodium::crypto::pwhash; 40 | //! 41 | //! let passwd = b"Correct Horse Battery Staple"; 42 | //! let salt = pwhash::gen_salt(); 43 | //! let mut k = secretbox::Key([0; secretbox::KEYBYTES]); 44 | //! { 45 | //! let secretbox::Key(ref mut kb) = k; 46 | //! pwhash::derive_key(kb, passwd, &salt, 47 | //! pwhash::OPSLIMIT_INTERACTIVE, 48 | //! pwhash::MEMLIMIT_INTERACTIVE).unwrap(); 49 | //! } 50 | //! ``` 51 | //! 52 | //! # Example (password hashing) 53 | //! ``` 54 | //! # #![allow(unused_variables)] 55 | //! use rust_sodium::crypto::pwhash; 56 | //! let passwd = b"Correct Horse Battery Staple"; 57 | //! let pwh = pwhash::pwhash(passwd, 58 | //! pwhash::OPSLIMIT_INTERACTIVE, 59 | //! pwhash::MEMLIMIT_INTERACTIVE).unwrap(); 60 | //! let pwh_bytes = &pwh[..]; 61 | //! //store pwh_bytes somewhere 62 | //! ``` 63 | //! 64 | //! # Example (password verification) 65 | //! ``` 66 | //! use rust_sodium::crypto::pwhash; 67 | //! 68 | //! let passwd = b"Correct Horse Battery Staple"; 69 | //! // in reality we want to load the password hash from somewhere 70 | //! // and we might want to create a `HashedPassword` from it using 71 | //! // `HashedPassword::from_slice(pwhash_bytes).unwrap()` 72 | //! let pwh = pwhash::pwhash(passwd, 73 | //! pwhash::OPSLIMIT_INTERACTIVE, 74 | //! pwhash::MEMLIMIT_INTERACTIVE).unwrap(); 75 | //! assert!(pwhash::pwhash_verify(&pwh, passwd)); 76 | //! ``` 77 | 78 | pub use self::scryptsalsa208sha256::*; 79 | pub mod scryptsalsa208sha256; 80 | -------------------------------------------------------------------------------- /src/crypto/pwhash/scryptsalsa208sha256.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! `crypto_pwhash_scryptsalsa208sha256`, a particular combination of Scrypt, Salsa20/8 11 | //! and SHA-256 12 | 13 | use crate::ffi; 14 | use crate::randombytes::randombytes_into; 15 | use libc::{c_char, c_ulonglong}; 16 | 17 | /// Number of bytes in a `Salt`. 18 | pub const SALTBYTES: usize = ffi::crypto_pwhash_scryptsalsa208sha256_SALTBYTES as usize; 19 | 20 | /// Number of bytes in a `HashedPassword`. 21 | pub const HASHEDPASSWORDBYTES: usize = ffi::crypto_pwhash_scryptsalsa208sha256_STRBYTES as usize; 22 | 23 | /// All `HashedPasswords` start with this string. 24 | pub const STRPREFIX: &str = "$7$"; 25 | 26 | /// Safe base line for `OpsLimit` for interactive password hashing. 27 | pub const OPSLIMIT_INTERACTIVE: OpsLimit = 28 | OpsLimit(ffi::crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE as usize); 29 | 30 | /// Safe base line for `MemLimit` for interactive password hashing. 31 | pub const MEMLIMIT_INTERACTIVE: MemLimit = 32 | MemLimit(ffi::crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE as usize); 33 | 34 | /// `OpsLimit` for highly sensitive data. 35 | pub const OPSLIMIT_SENSITIVE: OpsLimit = 36 | OpsLimit(ffi::crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE as usize); 37 | 38 | /// `MemLimit` for highly sensitive data. 39 | pub const MEMLIMIT_SENSITIVE: MemLimit = 40 | MemLimit(ffi::crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE as usize); 41 | 42 | /// `OpsLimit` represents the maximum number of computations to perform when 43 | /// using the functions in this module. 44 | /// 45 | /// A high `OpsLimit` will make the functions 46 | /// require more CPU cycles 47 | #[derive(Copy, Clone)] 48 | pub struct OpsLimit(pub usize); 49 | 50 | /// `MemLimit` represents the maximum amount of RAM that the functions in this 51 | /// module will use, in bytes. 52 | /// 53 | /// It is highly recommended to allow the functions to use 54 | /// at least 16 megabytes. 55 | #[derive(Copy, Clone)] 56 | pub struct MemLimit(pub usize); 57 | 58 | new_type! { 59 | /// `Salt` used for password hashing 60 | public Salt(SALTBYTES); 61 | } 62 | 63 | new_type! { 64 | /// `HashedPassword`is a password verifier generated from a password 65 | /// 66 | /// A `HashedPassword` is zero-terminated, includes only ASCII characters and can 67 | /// be conveniently stored into SQL databases and other data stores. No 68 | /// additional information has to be stored in order to verify the password. 69 | public HashedPassword(HASHEDPASSWORDBYTES); 70 | } 71 | 72 | /// `gen_salt()` randombly generates a new `Salt` for key derivation 73 | /// 74 | /// THREAD SAFETY: `gen_salt()` is thread-safe provided that you have called 75 | /// `rust_sodium::init()` once before using any other function from `rust_sodium`. 76 | pub fn gen_salt() -> Salt { 77 | let mut salt = Salt([0; SALTBYTES]); 78 | { 79 | let Salt(ref mut sb) = salt; 80 | randombytes_into(sb); 81 | } 82 | salt 83 | } 84 | 85 | /// The `derive_key()` function derives a key from a password and a `Salt` 86 | /// 87 | /// The computed key is stored into key. 88 | /// 89 | /// `opslimit` represents a maximum amount of computations to perform. Raising 90 | /// this number will make the function require more CPU cycles to compute a key. 91 | /// 92 | /// `memlimit` is the maximum amount of RAM that the function will use, in 93 | /// bytes. It is highly recommended to allow the function to use at least 16 94 | /// megabytes. 95 | /// 96 | /// For interactive, online operations, `OPSLIMIT_INTERACTIVE` and 97 | /// `MEMLIMIT_INTERACTIVE` provide a safe base line for these two 98 | /// parameters. However, using higher values may improve security. 99 | /// 100 | /// For highly sensitive data, `OPSLIMIT_SENSITIVE` and `MEMLIMIT_SENSITIVE` can 101 | /// be used as an alternative. But with these parameters, deriving a key takes 102 | /// more than 10 seconds on a 2.8 Ghz Core i7 CPU and requires up to 1 gigabyte 103 | /// of dedicated RAM. 104 | /// 105 | /// The salt should be unpredictable. `gen_salt()` is the easiest way to create a `Salt`. 106 | /// 107 | /// Keep in mind that in order to produce the same key from the same password, 108 | /// the same salt, and the same values for opslimit and memlimit have to be 109 | /// used. 110 | /// 111 | /// The function returns `Ok(key)` on success and `Err(())` if the computation didn't 112 | /// complete, usually because the operating system refused to allocate the 113 | /// amount of requested memory. 114 | pub fn derive_key<'a>( 115 | key: &'a mut [u8], 116 | passwd: &[u8], 117 | &Salt(ref sb): &Salt, 118 | OpsLimit(opslimit): OpsLimit, 119 | MemLimit(memlimit): MemLimit, 120 | ) -> Result<&'a [u8], ()> { 121 | if unsafe { 122 | ffi::crypto_pwhash_scryptsalsa208sha256( 123 | key.as_mut_ptr(), 124 | key.len() as c_ulonglong, 125 | passwd.as_ptr() as *const c_char, 126 | passwd.len() as c_ulonglong, 127 | sb.as_ptr(), 128 | opslimit as c_ulonglong, 129 | memlimit, 130 | ) 131 | } == 0 132 | { 133 | Ok(key) 134 | } else { 135 | Err(()) 136 | } 137 | } 138 | 139 | /// The `pwhash()` returns a `HashedPassword` which 140 | /// includes: 141 | /// 142 | /// - the result of a memory-hard, CPU-intensive hash function applied to the password 143 | /// `passwd` 144 | /// - the automatically generated salt used for the 145 | /// previous computation 146 | /// - the other parameters required to verify the password: opslimit and memlimit 147 | /// 148 | /// `OPSLIMIT_INTERACTIVE` and `MEMLIMIT_INTERACTIVE` are safe baseline 149 | /// values to use for `opslimit` and `memlimit`. 150 | /// 151 | /// The function returns `Ok(hashed_password)` on success and `Err(())` if it didn't complete 152 | /// successfully 153 | pub fn pwhash( 154 | passwd: &[u8], 155 | OpsLimit(opslimit): OpsLimit, 156 | MemLimit(memlimit): MemLimit, 157 | ) -> Result { 158 | let mut out = HashedPassword([0; HASHEDPASSWORDBYTES]); 159 | if unsafe { 160 | let HashedPassword(ref mut str_) = out; 161 | ffi::crypto_pwhash_scryptsalsa208sha256_str( 162 | str_.as_mut_ptr() as *mut c_char, 163 | passwd.as_ptr() as *const c_char, 164 | passwd.len() as c_ulonglong, 165 | opslimit as c_ulonglong, 166 | memlimit, 167 | ) 168 | } == 0 169 | { 170 | Ok(out) 171 | } else { 172 | Err(()) 173 | } 174 | } 175 | 176 | /// `pwhash_verify()` verifies that the password `str_` is a valid password 177 | /// verification string (as generated by `pwhash()`) for `passwd` 178 | /// 179 | /// It returns `true` if the verification succeeds, and `false` on error. 180 | pub fn pwhash_verify(&HashedPassword(ref str_): &HashedPassword, passwd: &[u8]) -> bool { 181 | unsafe { 182 | ffi::crypto_pwhash_scryptsalsa208sha256_str_verify( 183 | str_.as_ptr() as *const c_char, 184 | passwd.as_ptr() as *const c_char, 185 | passwd.len() as c_ulonglong, 186 | ) == 0 187 | } 188 | } 189 | 190 | #[cfg(test)] 191 | mod test { 192 | use super::*; 193 | use crate::ffi; 194 | use std::ffi::CStr; 195 | 196 | #[test] 197 | fn test_str_prefix() { 198 | unwrap!(crate::init()); 199 | let str_prefix = unsafe { 200 | unwrap!(CStr::from_ptr(ffi::crypto_pwhash_scryptsalsa208sha256_STRPREFIX).to_str()) 201 | }; 202 | assert_eq!(STRPREFIX, str_prefix); 203 | } 204 | 205 | #[test] 206 | #[rustfmt::skip] 207 | fn test_derive_key() { 208 | unwrap!(crate::init()); 209 | let mut kb = [0u8; 32]; 210 | let salt = Salt([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 211 | 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); 212 | let pw = b"Correct Horse Battery Staple"; 213 | // test vector generated by using libsodium 214 | let key_expected = [0xf1, 0xbb, 0xb8, 0x7c, 0x43, 0x36, 0x5b, 0x03, 0x3b, 0x9a, 0xe8, 215 | 0x3e, 0x05, 0xef, 0xad, 0x25, 0xdb, 0x8d, 0x83, 0xb8, 0x3d, 0xb1, 216 | 0xde, 0xe3, 0x6b, 0xdb, 0xf5, 0x4d, 0xcd, 0x3a, 0x1a, 0x11]; 217 | let key = unwrap!(derive_key(&mut kb, 218 | pw, 219 | &salt, 220 | OPSLIMIT_INTERACTIVE, 221 | MEMLIMIT_INTERACTIVE)); 222 | assert_eq!(key, key_expected); 223 | } 224 | 225 | #[test] 226 | fn test_pwhash_verify() { 227 | use crate::randombytes::randombytes; 228 | unwrap!(crate::init()); 229 | for i in 0..32usize { 230 | let pw = randombytes(i); 231 | let pwh = unwrap!(pwhash(&pw, OPSLIMIT_INTERACTIVE, MEMLIMIT_INTERACTIVE)); 232 | assert!(pwhash_verify(&pwh, &pw)); 233 | } 234 | } 235 | 236 | #[test] 237 | fn test_pwhash_verify_tamper() { 238 | use crate::randombytes::randombytes; 239 | unwrap!(crate::init()); 240 | for i in 0..16usize { 241 | let mut pw = randombytes(i); 242 | let pwh = unwrap!(pwhash(&pw, OPSLIMIT_INTERACTIVE, MEMLIMIT_INTERACTIVE)); 243 | for j in 0..pw.len() { 244 | pw[j] ^= 0x20; 245 | assert!(!pwhash_verify(&pwh, &pw)); 246 | pw[j] ^= 0x20; 247 | } 248 | } 249 | } 250 | 251 | #[test] 252 | fn test_serialisation() { 253 | use crate::randombytes::randombytes; 254 | use crate::test_utils::round_trip; 255 | unwrap!(crate::init()); 256 | for i in 0..32usize { 257 | let pw = randombytes(i); 258 | let pwh = unwrap!(pwhash(&pw, OPSLIMIT_INTERACTIVE, MEMLIMIT_INTERACTIVE)); 259 | let salt = gen_salt(); 260 | round_trip(&pwh); 261 | round_trip(&salt); 262 | } 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /src/crypto/scalarmult/curve25519.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! `crypto_scalarmult_curve25519` specified in 11 | //! [Cryptography in `NaCl`](http://nacl.cr.yp.to/valid.html), Sections 2, 3, and 4. 12 | //! This function is conjectured to be strong. For background see Bernstein, 13 | //! "Curve25519: new Diffie-Hellman speed records," Lecture Notes in Computer 14 | //! Science 3958 (2006), 207–228, . 15 | 16 | use crate::ffi; 17 | 18 | /// Number of bytes in a `GroupElement`. 19 | pub const GROUPELEMENTBYTES: usize = ffi::crypto_scalarmult_curve25519_BYTES as usize; 20 | 21 | /// Number of bytes in a `Scalar`. 22 | pub const SCALARBYTES: usize = ffi::crypto_scalarmult_curve25519_SCALARBYTES as usize; 23 | 24 | new_type! { 25 | /// `Scalar` value (integer in byte representation) 26 | secret Scalar(SCALARBYTES); 27 | } 28 | 29 | new_type! { 30 | /// `GroupElement` 31 | secret GroupElement(GROUPELEMENTBYTES); 32 | } 33 | 34 | /// `scalarmult()` multiplies a group element `p` 35 | /// by an integer `n`. It returns the resulting group element `Ok(q)`. 36 | /// If the the `GroupElement` is all zero, `scalarmult()` returns `Err(())` since 37 | /// the resulting `GroupElement` would be all zero, no matter the `Scalar`. 38 | pub fn scalarmult( 39 | &Scalar(ref n): &Scalar, 40 | &GroupElement(ref p): &GroupElement, 41 | ) -> Result { 42 | let mut q = [0; GROUPELEMENTBYTES]; 43 | unsafe { 44 | if ffi::crypto_scalarmult_curve25519(q.as_mut_ptr(), n.as_ptr(), p.as_ptr()) != 0 { 45 | Err(()) 46 | } else { 47 | Ok(GroupElement(q)) 48 | } 49 | } 50 | } 51 | 52 | /// `scalarmult_base()` computes the scalar product of a standard 53 | /// group element and an integer `n`. It returns the resulting 54 | /// group element `q`/ 55 | pub fn scalarmult_base(&Scalar(ref n): &Scalar) -> GroupElement { 56 | let mut q = [0; GROUPELEMENTBYTES]; 57 | unsafe { 58 | let _todo_use_result = ffi::crypto_scalarmult_curve25519_base(q.as_mut_ptr(), n.as_ptr()); 59 | } 60 | GroupElement(q) 61 | } 62 | 63 | #[cfg(test)] 64 | mod test { 65 | use super::*; 66 | use crate::randombytes::randombytes_into; 67 | 68 | #[test] 69 | #[rustfmt::skip] 70 | fn test_vector_1() { 71 | // corresponding to tests/scalarmult.c and tests/scalarmult3.cpp from NaCl 72 | unwrap!(crate::init()); 73 | let alicesk = Scalar([0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16, 0xc1, 74 | 0x72, 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 75 | 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a]); 76 | let alicepk_expected = [0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b, 0x7d, 77 | 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d, 0x26, 0x38, 78 | 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b, 0x4e, 0x6a]; 79 | let GroupElement(alicepk) = scalarmult_base(&alicesk); 80 | assert!(alicepk == alicepk_expected); 81 | } 82 | 83 | #[test] 84 | #[rustfmt::skip] 85 | fn test_vector_2() { 86 | // corresponding to tests/scalarmult2.c and tests/scalarmult4.cpp from NaCl 87 | unwrap!(crate::init()); 88 | let bobsk = Scalar([0x5d, 0xab, 0x08, 0x7e, 0x62, 0x4a, 0x8a, 0x4b, 0x79, 0xe1, 0x7f, 89 | 0x8b, 0x83, 0x80, 0x0e, 0xe6, 0x6f, 0x3b, 0xb1, 0x29, 0x26, 0x18, 90 | 0xb6, 0xfd, 0x1c, 0x2f, 0x8b, 0x27, 0xff, 0x88, 0xe0, 0xeb]); 91 | let bobpk_expected = [0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, 0xd3, 0x5b, 0x61, 92 | 0xc2, 0xec, 0xe4, 0x35, 0x37, 0x3f, 0x83, 0x43, 0xc8, 0x5b, 0x78, 93 | 0x67, 0x4d, 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f]; 94 | let GroupElement(bobpk) = scalarmult_base(&bobsk); 95 | assert!(bobpk == bobpk_expected); 96 | } 97 | 98 | #[test] 99 | #[rustfmt::skip] 100 | fn test_vector_3() { 101 | // corresponding to tests/scalarmult5.c and tests/scalarmult7.cpp from NaCl 102 | unwrap!(crate::init()); 103 | let alicesk = Scalar([0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16, 0xc1, 104 | 0x72, 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 105 | 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a]); 106 | let bobpk = GroupElement([0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, 0xd3, 0x5b, 107 | 0x61, 0xc2, 0xec, 0xe4, 0x35, 0x37, 0x3f, 0x83, 0x43, 0xc8, 108 | 0x5b, 0x78, 0x67, 0x4d, 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 109 | 0x2b, 0x4f]); 110 | let k_expected = [0x4a, 0x5d, 0x9d, 0x5b, 0xa4, 0xce, 0x2d, 0xe1, 0x72, 0x8e, 0x3b, 0xf4, 111 | 0x80, 0x35, 0x0f, 0x25, 0xe0, 0x7e, 0x21, 0xc9, 0x47, 0xd1, 0x9e, 0x33, 112 | 0x76, 0xf0, 0x9b, 0x3c, 0x1e, 0x16, 0x17, 0x42]; 113 | let GroupElement(k) = unwrap!(scalarmult(&alicesk, &bobpk)); 114 | assert!(k == k_expected); 115 | } 116 | 117 | #[test] 118 | #[rustfmt::skip] 119 | fn test_vector_4() { 120 | // corresponding to tests/scalarmult6.c from NaCl 121 | unwrap!(crate::init()); 122 | let bobsk = Scalar([0x5d, 0xab, 0x08, 0x7e, 0x62, 0x4a, 0x8a, 0x4b, 0x79, 0xe1, 0x7f, 123 | 0x8b, 0x83, 0x80, 0x0e, 0xe6, 0x6f, 0x3b, 0xb1, 0x29, 0x26, 0x18, 124 | 0xb6, 0xfd, 0x1c, 0x2f, 0x8b, 0x27, 0xff, 0x88, 0xe0, 0xeb]); 125 | let alicepk = GroupElement([0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b, 126 | 0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d, 127 | 0x26, 0x38, 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b, 128 | 0x4e, 0x6a]); 129 | let k_expected = [0x4a, 0x5d, 0x9d, 0x5b, 0xa4, 0xce, 0x2d, 0xe1, 0x72, 0x8e, 0x3b, 0xf4, 130 | 0x80, 0x35, 0x0f, 0x25, 0xe0, 0x7e, 0x21, 0xc9, 0x47, 0xd1, 0x9e, 0x33, 131 | 0x76, 0xf0, 0x9b, 0x3c, 0x1e, 0x16, 0x17, 0x42]; 132 | let GroupElement(k) = unwrap!(scalarmult(&bobsk, &alicepk)); 133 | assert!(k == k_expected); 134 | } 135 | 136 | #[test] 137 | #[should_panic] 138 | fn test_all_zero() { 139 | unwrap!(crate::init()); 140 | let mut sk = [0; SCALARBYTES]; 141 | randombytes_into(&mut sk); 142 | let sk = Scalar(sk); 143 | let pk = GroupElement([0; GROUPELEMENTBYTES]); 144 | let _ = unwrap!(scalarmult(&sk, &pk)); 145 | } 146 | } 147 | 148 | #[cfg(feature = "benchmarks")] 149 | #[cfg(test)] 150 | mod bench { 151 | extern crate test; 152 | use super::*; 153 | use crate::randombytes::randombytes_into; 154 | 155 | #[bench] 156 | fn bench_scalarmult(b: &mut test::Bencher) { 157 | unwrap!(crate::init()); 158 | let mut gbs = [0u8; GROUPELEMENTBYTES]; 159 | let mut sbs = [0u8; SCALARBYTES]; 160 | randombytes_into(&mut gbs); 161 | randombytes_into(&mut sbs); 162 | let g = GroupElement(gbs); 163 | let s = Scalar(sbs); 164 | b.iter(|| { 165 | scalarmult(&s, &g); 166 | }); 167 | } 168 | 169 | #[bench] 170 | fn bench_scalarmult_base(b: &mut test::Bencher) { 171 | unwrap!(crate::init()); 172 | let mut sbs = [0u8; SCALARBYTES]; 173 | randombytes_into(&mut sbs); 174 | let s = Scalar(sbs); 175 | b.iter(|| { 176 | scalarmult_base(&s); 177 | }); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/crypto/scalarmult/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Scalar multiplication 11 | //! 12 | //! # Representation of group elements 13 | //! The correspondence between strings and group elements depends on the primitive 14 | //! implemented by `scalarmult()`. The correspondence is not necessarily 15 | //! injective in either direction, but it is compatible with scalar multiplication 16 | //! in the group. The correspondence does not necessarily include all group 17 | //! elements, but it does include all strings; i.e., every string represents at 18 | //! least one group element. 19 | //! 20 | //! # Representation of integers 21 | //! The correspondence between strings and integers also depends on the primitive 22 | //! implemented by `scalarmult()`. Every string represents at least one integer. 23 | //! 24 | //! # Security model 25 | //! `scalarmult` is designed to be strong as a component of various well-known 26 | //! "hashed Diffie–Hellman" applications. In particular, it is designed to make the 27 | //! "computational Diffie–Hellman" problem (CDH) difficult with respect to the 28 | //! standard base. 29 | //! 30 | //! `scalarmult` is also designed to make CDH difficult with respect to other 31 | //! nontrivial bases. In particular, if a represented group element has small 32 | //! order, then it is annihilated by all represented scalars. This feature allows 33 | //! protocols to avoid validating membership in the subgroup generated by the 34 | //! standard base. 35 | //! 36 | //! `NaCl` does not make any promises regarding the "decisional Diffie–Hellman" 37 | //! problem (DDH), the "static Diffie–Hellman" problem (SDH), etc. Users are 38 | //! responsible for hashing group elements. 39 | //! 40 | //! # Selected primitive 41 | //! `scalarmult` is the function `crypto_scalarmult_curve25519` specified in 42 | //! [Cryptography in `NaCl`](http://nacl.cr.yp.to/valid.html), Sections 2, 3, and 4. 43 | //! This function is conjectured to be strong. For background see Bernstein, 44 | //! "Curve25519: new Diffie-Hellman speed records," Lecture Notes in Computer 45 | //! Science 3958 (2006), 207–228, . 46 | 47 | pub use self::curve25519::*; 48 | pub mod curve25519; 49 | -------------------------------------------------------------------------------- /src/crypto/sealedbox/curve25519blake2bxsalsa20poly1305.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! A particular combination of `Curve25519`, `Blake2B`, `Salsa20` and `Poly1305`. 11 | 12 | use super::super::box_::curve25519xsalsa20poly1305 as box_; 13 | use crate::ffi; 14 | 15 | use libc::c_ulonglong; 16 | 17 | /// Number of additional bytes in a ciphertext compared to the corresponding 18 | /// plaintext. 19 | pub const SEALBYTES: usize = ffi::crypto_box_SEALBYTES as usize; 20 | 21 | /// The `seal()` function encrypts a message `m` for a recipient whose public key 22 | /// is `pk`. It returns the ciphertext whose length is `SEALBYTES + m.len()`. 23 | /// 24 | /// The function creates a new key pair for each message, and attaches the public 25 | /// key to the ciphertext. The secret key is overwritten and is not accessible 26 | /// after this function returns. 27 | pub fn seal(m: &[u8], &box_::PublicKey(ref pk): &box_::PublicKey) -> Vec { 28 | let mut c = vec![0u8; m.len() + SEALBYTES]; 29 | unsafe { 30 | let _todo_use_result = ffi::crypto_box_seal( 31 | c.as_mut_ptr(), 32 | m.as_ptr(), 33 | m.len() as c_ulonglong, 34 | pk.as_ptr(), 35 | ); 36 | } 37 | c 38 | } 39 | 40 | /// The `open()` function decrypts the ciphertext `c` using the key pair `(pk, sk)` 41 | /// and returns the decrypted message. 42 | /// 43 | /// Key pairs are compatible with other 44 | /// `crypto::box_::curve25519xsalsa20poly1305` operations and can be created 45 | /// using `crypto::box::gen_keypair()`. 46 | /// 47 | /// This function doesn't require passing the public key of the sender, as the 48 | /// ciphertext already includes this information. 49 | /// 50 | /// If decryption fails it returns `Err(())`. 51 | pub fn open( 52 | c: &[u8], 53 | &box_::PublicKey(ref pk): &box_::PublicKey, 54 | &box_::SecretKey(ref sk): &box_::SecretKey, 55 | ) -> Result, ()> { 56 | if c.len() < SEALBYTES { 57 | return Err(()); 58 | } 59 | let mut m = vec![0u8; c.len() - SEALBYTES]; 60 | let ret = unsafe { 61 | ffi::crypto_box_seal_open( 62 | m.as_mut_ptr(), 63 | c.as_ptr(), 64 | c.len() as c_ulonglong, 65 | pk.as_ptr(), 66 | sk.as_ptr(), 67 | ) 68 | }; 69 | if ret == 0 { 70 | Ok(m) 71 | } else { 72 | Err(()) 73 | } 74 | } 75 | 76 | #[cfg(test)] 77 | mod test { 78 | use super::super::super::box_::curve25519xsalsa20poly1305 as box_; 79 | use super::*; 80 | 81 | #[test] 82 | fn test_seal_open() { 83 | use crate::randombytes::randombytes; 84 | unwrap!(crate::init()); 85 | for i in 0..256usize { 86 | let (pk, sk) = box_::gen_keypair(); 87 | let m = randombytes(i); 88 | let c = seal(&m, &pk); 89 | let opened = open(&c, &pk, &sk); 90 | assert!(Ok(m) == opened); 91 | } 92 | } 93 | 94 | #[test] 95 | fn test_seal_open_tamper() { 96 | use crate::randombytes::randombytes; 97 | unwrap!(crate::init()); 98 | for i in 0..32usize { 99 | let (pk, sk) = box_::gen_keypair(); 100 | let m = randombytes(i); 101 | let mut c = seal(&m, &pk); 102 | for j in 0..c.len() { 103 | c[j] ^= 0x20; 104 | assert!(Err(()) == open(&c, &pk, &sk)); 105 | c[j] ^= 0x20; 106 | } 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/crypto/sealedbox/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Sealed Boxes 11 | //! 12 | //! # Purpose 13 | //! Sealed boxes are designed to anonymously send messages to a recipient given 14 | //! its public key. 15 | //! 16 | //! Only the recipient can decrypt these messages, using its private key. While 17 | //! the recipient can verify the integrity of the message, it cannot verify the 18 | //! identity of the sender. 19 | //! 20 | //! A message is encrypted using an ephemeral key pair, whose secret part is 21 | //! destroyed right after the encryption process. 22 | //! 23 | //! Without knowing the secret key used for a given message, the sender cannot 24 | //! decrypt its own message later. And without additional data, a message 25 | //! cannot be correlated with the identity of its sender. 26 | //! 27 | //! # Algorithm Details 28 | //! Sealed boxes leverage the `crypto_box` construction (X25519, XSalsa20-Poly1305). 29 | //! 30 | //! The format of a sealed box is 31 | //! 32 | //! ```c 33 | //! ephemeral_pk || box(m, recipient_pk, ephemeral_sk, 34 | //! nonce=blake2b(ephemeral_pk, recipient_pk)) 35 | //! ``` 36 | //! 37 | 38 | pub use self::curve25519blake2bxsalsa20poly1305::*; 39 | pub mod curve25519blake2bxsalsa20poly1305; 40 | -------------------------------------------------------------------------------- /src/crypto/secretbox/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Secret-key authenticated encryption 11 | //! 12 | //! # Security model 13 | //! The `seal()` function is designed to meet the standard notions of privacy and 14 | //! authenticity for a secret-key authenticated-encryption scheme using nonces. For 15 | //! formal definitions see, e.g., Bellare and Namprempre, "Authenticated 16 | //! encryption: relations among notions and analysis of the generic composition 17 | //! paradigm," Lecture Notes in Computer Science 1976 (2000), 531–545, 18 | //! . 19 | //! 20 | //! Note that the length is not hidden. Note also that it is the caller's 21 | //! responsibility to ensure the uniqueness of nonces—for example, by using 22 | //! nonce 1 for the first message, nonce 2 for the second message, etc. 23 | //! Nonces are long enough that randomly generated nonces have negligible 24 | //! risk of collision. 25 | //! 26 | //! # Selected primitive 27 | //! `seal()` is `crypto_secretbox_xsalsa20poly1305`, a particular 28 | //! combination of Salsa20 and Poly1305 specified in 29 | //! [Cryptography in `NaCl`](http://nacl.cr.yp.to/valid.html). 30 | //! 31 | //! This function is conjectured to meet the standard notions of privacy and 32 | //! authenticity. 33 | //! 34 | //! # Example 35 | //! ``` 36 | //! use rust_sodium::crypto::secretbox; 37 | //! let key = secretbox::gen_key(); 38 | //! let nonce = secretbox::gen_nonce(); 39 | //! let plaintext = b"some data"; 40 | //! let ciphertext = secretbox::seal(plaintext, &nonce, &key); 41 | //! let their_plaintext = secretbox::open(&ciphertext, &nonce, &key).unwrap(); 42 | //! assert!(plaintext == &their_plaintext[..]); 43 | //! ``` 44 | 45 | pub use self::xsalsa20poly1305::*; 46 | pub mod xsalsa20poly1305; 47 | -------------------------------------------------------------------------------- /src/crypto/shorthash/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! A lot of applications and programming language implementations have been 11 | //! recently found to be vulnerable to denial-of-service attacks when a hash 12 | //! function with weak security guarantees, like Murmurhash 3, was used to 13 | //! construct a hash table. 14 | //! 15 | //! In order to address this, Sodium provides the `shorthash()` function. 16 | //! This very fast hash functions outputs short, but unpredictable 17 | //! (without knowing the secret key) values suitable for picking a list in 18 | //! a hash table for a given key. 19 | //! 20 | //! # Selected primitive 21 | //! `shorthash()` is currently an implementation of `SipHash-2-4` as specified in 22 | //! [`SipHash`: a fast short-input PRF](https://131002.net/siphash/) 23 | //! 24 | //! # Example 25 | //! ``` 26 | //! # #![allow(unused_variables)] 27 | //! use rust_sodium::crypto::shorthash; 28 | //! 29 | //! let key = shorthash::gen_key(); 30 | //! let data_to_hash = b"some data"; 31 | //! let digest = shorthash::shorthash(data_to_hash, &key); 32 | //! ``` 33 | 34 | pub use self::siphash24::*; 35 | pub mod siphash24; 36 | -------------------------------------------------------------------------------- /src/crypto/shorthash/siphash24.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! `SipHash-2-4` 11 | 12 | use crate::ffi; 13 | use crate::randombytes::randombytes_into; 14 | use libc::c_ulonglong; 15 | 16 | /// Number of bytes in a `Digest`. 17 | pub const DIGESTBYTES: usize = ffi::crypto_shorthash_siphash24_BYTES as usize; 18 | 19 | /// Number of bytes in a `Key`. 20 | pub const KEYBYTES: usize = ffi::crypto_shorthash_siphash24_KEYBYTES as usize; 21 | 22 | new_type! { 23 | /// `Digest` structure 24 | public Digest(DIGESTBYTES); 25 | } 26 | 27 | new_type! { 28 | /// `Key` 29 | /// 30 | /// When a `Key` goes out of scope its contents will be zeroed out. 31 | secret Key(KEYBYTES); 32 | } 33 | 34 | /// `gen_key()` randomly generates a key for shorthash 35 | /// 36 | /// THREAD SAFETY: `gen_key()` is thread-safe provided that you have 37 | /// called `rust_sodium::init()` once before using any other function 38 | /// from `rust_sodium`. 39 | pub fn gen_key() -> Key { 40 | let mut k = [0; KEYBYTES]; 41 | randombytes_into(&mut k); 42 | Key(k) 43 | } 44 | 45 | /// `shorthash` hashes a message `m` under a key `k`. It 46 | /// returns a hash `h`. 47 | pub fn shorthash(m: &[u8], &Key(ref k): &Key) -> Digest { 48 | unsafe { 49 | let mut h = [0; DIGESTBYTES]; 50 | let _todo_use_result = ffi::crypto_shorthash_siphash24( 51 | h.as_mut_ptr(), 52 | m.as_ptr(), 53 | m.len() as c_ulonglong, 54 | k.as_ptr(), 55 | ); 56 | Digest(h) 57 | } 58 | } 59 | 60 | #[cfg(test)] 61 | mod test { 62 | use super::*; 63 | 64 | #[test] 65 | fn test_vectors() { 66 | unwrap!(crate::init()); 67 | let maxlen = 64; 68 | let mut m = Vec::with_capacity(64); 69 | for i in 0usize..64 { 70 | m.push(i as u8); 71 | } 72 | let h_expecteds = [ 73 | [0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72], 74 | [0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74], 75 | [0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d], 76 | [0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85], 77 | [0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf], 78 | [0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18], 79 | [0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb], 80 | [0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab], 81 | [0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93], 82 | [0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e], 83 | [0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a], 84 | [0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4], 85 | [0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75], 86 | [0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14], 87 | [0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7], 88 | [0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1], 89 | [0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f], 90 | [0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69], 91 | [0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b], 92 | [0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb], 93 | [0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe], 94 | [0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0], 95 | [0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93], 96 | [0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8], 97 | [0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8], 98 | [0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc], 99 | [0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17], 100 | [0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f], 101 | [0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde], 102 | [0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6], 103 | [0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad], 104 | [0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32], 105 | [0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71], 106 | [0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7], 107 | [0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12], 108 | [0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15], 109 | [0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31], 110 | [0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02], 111 | [0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca], 112 | [0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a], 113 | [0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e], 114 | [0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad], 115 | [0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18], 116 | [0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4], 117 | [0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9], 118 | [0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9], 119 | [0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb], 120 | [0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0], 121 | [0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6], 122 | [0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7], 123 | [0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee], 124 | [0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1], 125 | [0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a], 126 | [0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81], 127 | [0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f], 128 | [0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24], 129 | [0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7], 130 | [0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea], 131 | [0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60], 132 | [0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66], 133 | [0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c], 134 | [0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f], 135 | [0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5], 136 | [0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95], 137 | ]; 138 | let k = Key([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); 139 | for i in 0usize..maxlen { 140 | let Digest(h) = shorthash(&m[..i], &k); 141 | assert!(h == h_expecteds[i]); 142 | } 143 | } 144 | 145 | #[test] 146 | fn test_serialisation() { 147 | use crate::randombytes::randombytes; 148 | use crate::test_utils::round_trip; 149 | unwrap!(crate::init()); 150 | for i in 0..64usize { 151 | let k = gen_key(); 152 | let m = randombytes(i); 153 | let d = shorthash(&m[..], &k); 154 | round_trip(&k); 155 | round_trip(&d); 156 | } 157 | } 158 | } 159 | 160 | #[cfg(feature = "benchmarks")] 161 | #[cfg(test)] 162 | mod bench { 163 | extern crate test; 164 | use super::*; 165 | use crate::randombytes::randombytes; 166 | 167 | const BENCH_SIZES: [usize; 14] = [0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096]; 168 | 169 | #[bench] 170 | fn bench_shorthash(b: &mut test::Bencher) { 171 | unwrap!(crate::init()); 172 | let k = gen_key(); 173 | let ms: Vec> = BENCH_SIZES.iter().map(|s| randombytes(*s)).collect(); 174 | b.iter(|| { 175 | for m in ms.iter() { 176 | shorthash(m, &k); 177 | } 178 | }); 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/crypto/sign/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Public-key signatures 11 | //! 12 | //! This module re-exports all members of the default signing scheme, currently 13 | //! [`ed25519`](ed25519/index.html), hence e.g. `sign` refers to 14 | //! [`ed25519::sign`](ed25519/fn.sign.html). 15 | //! 16 | //! # Security model 17 | //! The [`sign()`](ed25519/fn.sign.html) function is designed to meet the standard 18 | //! notion of unforgeability for a public-key signature scheme under 19 | //! chosen-message attacks. 20 | //! 21 | //! # Selected primitive 22 | //! [`crypto::sign::sign`](ed25519/fn.sign.html) is `ed25519`, a signature scheme specified in 23 | //! [Ed25519](http://ed25519.cr.yp.to/). This function is conjectured to meet the 24 | //! standard notion of unforgeability for a public-key signature scheme under 25 | //! chosen-message attacks. 26 | //! 27 | //! # Alternate primitives 28 | //! 29 | //! ---------------------------------------------------------------------------------- 30 | //! |`crypto_sign` | PUBLICKEYBYTES | SECRETKEYBYTES | BYTES | 31 | //! |--------------------------------------|----------------|----------------|-------| 32 | //! |`crypto_sign_ed25519` | 32 | 64 | 64 | 33 | //! |`crypto_sign_edwards25519sha512batch` | 32 | 64 | 64 | 34 | //! ---------------------------------------------------------------------------------- 35 | //! 36 | //! `crypto_sign_edwards25519sha512batch` is a prototype. It has been replaced with 37 | //! Ed25519 and is only kept here for compatibility reasons. 38 | //! 39 | //! # Example 40 | //! ``` 41 | //! use rust_sodium::crypto::sign; 42 | //! let (pk, sk) = sign::gen_keypair(); 43 | //! let data_to_sign = b"some data"; 44 | //! let signed_data = sign::sign(data_to_sign, &sk); 45 | //! let verified_data = sign::verify(&signed_data, &pk).unwrap(); 46 | //! assert!(data_to_sign == &verified_data[..]); 47 | //! ``` 48 | //! 49 | //! # Example (detached signatures) 50 | //! ``` 51 | //! use rust_sodium::crypto::sign; 52 | //! let (pk, sk) = sign::gen_keypair(); 53 | //! let data_to_sign = b"some data"; 54 | //! let signature = sign::sign_detached(data_to_sign, &sk); 55 | //! assert!(sign::verify_detached(&signature, data_to_sign, &pk)); 56 | //! ``` 57 | 58 | pub use self::ed25519::*; 59 | 60 | pub mod ed25519; 61 | -------------------------------------------------------------------------------- /src/crypto/stream/chacha20.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! `crypto_stream_chacha20` (Chacha20) 11 | 12 | use crate::ffi::{ 13 | crypto_stream_chacha20, crypto_stream_chacha20_KEYBYTES, crypto_stream_chacha20_NONCEBYTES, 14 | crypto_stream_chacha20_xor, crypto_stream_chacha20_xor_ic, 15 | }; 16 | 17 | stream_module!( 18 | crypto_stream_chacha20, 19 | crypto_stream_chacha20_xor, 20 | crypto_stream_chacha20_xor_ic, 21 | crypto_stream_chacha20_KEYBYTES as usize, 22 | crypto_stream_chacha20_NONCEBYTES as usize 23 | ); 24 | 25 | #[cfg(test)] 26 | mod test { 27 | use super::*; 28 | 29 | #[test] 30 | #[rustfmt::skip] 31 | fn test_vector_1() { 32 | // the fifth test from 33 | // https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7 34 | unwrap!(crate::init()); 35 | let key = Key([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 36 | 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 37 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f]); 38 | let nonce = Nonce([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]); 39 | let expected = 40 | [0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69, 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 41 | 0xb7, 0x75, 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93, 0xec, 0x01, 0xac, 0x56, 42 | 0xf8, 0x5a, 0xc3, 0xc1, 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41, 0x30, 0x42, 43 | 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69, 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1, 44 | 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a, 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 45 | 0x35, 0x94, 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66, 0x89, 0xde, 0x95, 0x26, 46 | 0x49, 0x86, 0xd9, 0x58, 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd, 0x9a, 0x5a, 47 | 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56, 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e, 48 | 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e, 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 49 | 0x31, 0xc7, 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15, 0x1b, 0x9a, 0x47, 0x50, 50 | 0x32, 0xb6, 0x3f, 0xc3, 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a, 0x97, 0xa5, 51 | 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25, 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5, 52 | 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69, 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 53 | 0xc9, 0xc4, 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7, 0x0e, 0xaf, 0x46, 0xf7, 54 | 0x6d, 0xad, 0x39, 0x79, 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a, 0x1c, 0x89, 55 | 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a, 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2, 56 | 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a, 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 57 | 0x54, 0x09, 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a, 0x6d, 0xeb, 0x3a, 0xb7, 58 | 0x8f, 0xab, 0x78, 0xc9]; 59 | let output = stream(expected.len(), &nonce, &key); 60 | assert!(output[..] == expected[..]); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/crypto/stream/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Secret-key encryption 11 | //! 12 | //! # Security Model 13 | //! The `stream()` function, viewed as a function of the nonce for a 14 | //! uniform random key, is designed to meet the standard notion of 15 | //! unpredictability ("PRF"). For a formal definition see, e.g., Section 2.3 16 | //! of Bellare, Kilian, and Rogaway, "The security of the cipher block 17 | //! chaining message authentication code," Journal of Computer and System 18 | //! Sciences 61 (2000), 362–399; 19 | //! . 20 | //! 21 | //! This means that an attacker cannot distinguish this function from a 22 | //! uniform random function. Consequently, if a series of messages is 23 | //! encrypted by `stream_xor()` with a different nonce for each message, 24 | //! the ciphertexts are indistinguishable from uniform random strings of the 25 | //! same length. 26 | //! 27 | //! Note that the length is not hidden. Note also that it is the caller's 28 | //! responsibility to ensure the uniqueness of nonces—for example, by using 29 | //! nonce 1 for the first message, nonce 2 for the second message, etc. 30 | //! Nonces are long enough that randomly generated nonces have negligible 31 | //! risk of collision. 32 | //! 33 | //! `NaCl` does not make any promises regarding the resistance of `stream()` to 34 | //! "related-key attacks." It is the caller's responsibility to use proper 35 | //! key-derivation functions. 36 | //! 37 | //! # Selected primitive 38 | //! `stream()` is `crypto_stream_xsalsa20`, a particular cipher specified in 39 | //! [Cryptography in `NaCl`](http://nacl.cr.yp.to/valid.html), Section 7. 40 | //! This cipher is conjectured to meet the standard notion of 41 | //! unpredictability. 42 | //! 43 | //! # Alternate primitives 44 | //! `NaCl` supports the following secret-key encryption functions: 45 | //! 46 | //! -------------------------------------------------------------- 47 | //! |`crypto_stream` |primitive |KEYBYTES |NONCEBYTES| 48 | //! |--------------------------|------------|---------|----------| 49 | //! |`crypto_stream_chacha20` |Chacha20/20 |32 |8 | 50 | //! |`crypto_stream_salsa20` |Salsa20/20 |32 |8 | 51 | //! |`crypto_stream_xsalsa20` |XSalsa20/20 |32 |24 | 52 | //! |`crypto_stream_xchacha20` |XChacha20/20|32 |24 | 53 | //! -------------------------------------------------------------- 54 | //! 55 | //! Beware that several of these primitives have 8-byte nonces. For those 56 | //! primitives it is no longer true that randomly generated nonces have negligible 57 | //! risk of collision. Callers who are unable to count 1, 2, 3..., and who insist 58 | //! on using these primitives, are advised to use a randomly derived key for each 59 | //! message. 60 | //! 61 | //! # Example (keystream generation) 62 | //! ``` 63 | //! # #![allow(unused_variables)] 64 | //! use rust_sodium::crypto::stream; 65 | //! 66 | //! let key = stream::gen_key(); 67 | //! let nonce = stream::gen_nonce(); 68 | //! let keystream = stream::stream(128, &nonce, &key); // generate 128 bytes of keystream 69 | //! ``` 70 | //! 71 | //! # Example (encryption) 72 | //! ``` 73 | //! use rust_sodium::crypto::stream; 74 | //! 75 | //! let key = stream::gen_key(); 76 | //! let nonce = stream::gen_nonce(); 77 | //! let plaintext = b"some data"; 78 | //! let ciphertext = stream::stream_xor(plaintext, &nonce, &key); 79 | //! let their_plaintext = stream::stream_xor(&ciphertext, &nonce, &key); 80 | //! assert_eq!(plaintext, &their_plaintext[..]); 81 | //! ``` 82 | //! 83 | //! # Example (in place encryption) 84 | //! ``` 85 | //! use rust_sodium::crypto::stream; 86 | //! 87 | //! let key = stream::gen_key(); 88 | //! let nonce = stream::gen_nonce(); 89 | //! let plaintext = &mut [0, 1, 2, 3]; 90 | //! // encrypt the plaintext 91 | //! stream::stream_xor_inplace(plaintext, &nonce, &key); 92 | //! // decrypt the plaintext 93 | //! stream::stream_xor_inplace(plaintext, &nonce, &key); 94 | //! assert_eq!(plaintext, &mut [0, 1, 2, 3]); 95 | //! ``` 96 | 97 | pub use self::xsalsa20::*; 98 | #[macro_use] 99 | mod stream_macros; 100 | pub mod chacha20; 101 | pub mod salsa20; 102 | pub mod xchacha20; 103 | pub mod xsalsa20; 104 | -------------------------------------------------------------------------------- /src/crypto/stream/salsa20.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! `crypto_stream_salsa20` (Salsa20/20), a particular cipher specified in 11 | //! [Cryptography in `NaCl`](http://nacl.cr.yp.to/valid.html), Section 7. This 12 | //! cipher is conjectured to meet the standard notion of unpredictability. 13 | 14 | use crate::ffi::{ 15 | crypto_stream_salsa20, crypto_stream_salsa20_KEYBYTES, crypto_stream_salsa20_NONCEBYTES, 16 | crypto_stream_salsa20_xor, crypto_stream_salsa20_xor_ic, 17 | }; 18 | 19 | stream_module!( 20 | crypto_stream_salsa20, 21 | crypto_stream_salsa20_xor, 22 | crypto_stream_salsa20_xor_ic, 23 | crypto_stream_salsa20_KEYBYTES as usize, 24 | crypto_stream_salsa20_NONCEBYTES as usize 25 | ); 26 | 27 | #[cfg(test)] 28 | mod test { 29 | use super::*; 30 | 31 | #[test] 32 | #[rustfmt::skip] 33 | fn test_vector_1() { 34 | // corresponding to tests/stream2.c and tests/stream6.cpp from NaCl 35 | unwrap!(crate::init()); 36 | use crate::crypto::hash::sha256::{Digest, hash}; 37 | let secondkey = Key([0xdc, 0x90, 0x8d, 0xda, 0x0b, 0x93, 0x44, 0xa9, 0x53, 0x62, 0x9b, 38 | 0x73, 0x38, 0x20, 0x77, 0x88, 0x80, 0xf3, 0xce, 0xb4, 0x21, 0xbb, 39 | 0x61, 0xb9, 0x1c, 0xbd, 0x4c, 0x3e, 0x66, 0x25, 0x6c, 0xe4]); 40 | let noncesuffix = Nonce([0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 0x0b, 0x37]); 41 | let output = stream(0x40_0000, &noncesuffix, &secondkey); 42 | let digest_expected = [0x66, 0x2b, 0x9d, 0x0e, 0x34, 0x63, 0x02, 0x91, 0x56, 0x06, 0x9b, 43 | 0x12, 0xf9, 0x18, 0x69, 0x1a, 0x98, 0xf7, 0xdf, 0xb2, 0xca, 0x03, 44 | 0x93, 0xc9, 0x6b, 0xbf, 0xc6, 0xb1, 0xfb, 0xd6, 0x30, 0xa2]; 45 | let Digest(digest) = hash(&output); 46 | assert!(digest == digest_expected); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/crypto/stream/stream_macros.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | macro_rules! stream_module (($stream_name:ident, 11 | $xor_name:ident, 12 | $xor_ic_name:ident, 13 | $keybytes:expr, 14 | $noncebytes:expr) => ( 15 | 16 | use libc::c_ulonglong; 17 | use crate::randombytes::randombytes_into; 18 | 19 | /// Number of bytes in a `Key`. 20 | pub const KEYBYTES: usize = $keybytes; 21 | 22 | /// Number of bytes in a `Nonce`. 23 | pub const NONCEBYTES: usize = $noncebytes; 24 | 25 | new_type! { 26 | /// `Key` for symmetric encryption 27 | /// 28 | /// When a `Key` goes out of scope its contents 29 | /// will be zeroed out 30 | secret Key(KEYBYTES); 31 | } 32 | 33 | new_type! { 34 | /// `Nonce` for symmetric encryption 35 | nonce Nonce(NONCEBYTES); 36 | } 37 | 38 | /// `gen_key()` randomly generates a key for symmetric encryption 39 | /// 40 | /// THREAD SAFETY: `gen_key()` is thread-safe provided that you have 41 | /// called `rust_sodium::init()` once before using any other function 42 | /// from `rust_sodium`. 43 | pub fn gen_key() -> Key { 44 | let mut key = [0; KEYBYTES]; 45 | randombytes_into(&mut key); 46 | Key(key) 47 | } 48 | 49 | /// `gen_nonce()` randomly generates a nonce for symmetric encryption 50 | /// 51 | /// THREAD SAFETY: `gen_nonce()` is thread-safe provided that you have 52 | /// called `rust_sodium::init()` once before using any other function 53 | /// from `rust_sodium`. 54 | /// 55 | /// NOTE: When using primitives with short nonces (e.g. salsa20, salsa208, salsa2012) 56 | /// do not use random nonces since the probability of nonce-collision is not negligible 57 | pub fn gen_nonce() -> Nonce { 58 | let mut nonce = [0; NONCEBYTES]; 59 | randombytes_into(&mut nonce); 60 | Nonce(nonce) 61 | } 62 | 63 | /// `stream()` produces a `len`-byte stream `c` as a function of a 64 | /// secret key `k` and a nonce `n`. 65 | pub fn stream(len: usize, 66 | &Nonce(ref n): &Nonce, 67 | &Key(ref k): &Key) -> Vec { 68 | unsafe { 69 | let mut c = vec![0u8; len]; 70 | let _todo_use_result = $stream_name(c.as_mut_ptr(), 71 | c.len() as c_ulonglong, 72 | n.as_ptr(), 73 | k.as_ptr()); 74 | c 75 | } 76 | } 77 | 78 | /// `stream_xor()` encrypts a message `m` using a secret key `k` and a nonce `n`. 79 | /// The `stream_xor()` function returns the ciphertext `c`. 80 | /// 81 | /// `stream_xor()` guarantees that the ciphertext has the same length as the plaintext, 82 | /// and is the plaintext xor the output of `stream()`. 83 | /// Consequently `stream_xor()` can also be used to decrypt. 84 | pub fn stream_xor(m: &[u8], 85 | &Nonce(ref n): &Nonce, 86 | &Key(ref k): &Key) -> Vec { 87 | unsafe { 88 | let mut c = vec![0u8; m.len()]; 89 | let _todo_use_result = $xor_name(c.as_mut_ptr(), 90 | m.as_ptr(), 91 | m.len() as c_ulonglong, 92 | n.as_ptr(), 93 | k.as_ptr()); 94 | c 95 | } 96 | } 97 | 98 | /// `stream_xor_inplace()` encrypts a message `m` using a secret key `k` and a nonce `n`. 99 | /// The `stream_xor_inplace()` function encrypts the message in place. 100 | /// 101 | /// `stream_xor_inplace()` guarantees that the ciphertext has the same length as 102 | /// the plaintext, and is the plaintext xor the output of `stream_inplace()`. 103 | /// Consequently `stream_xor_inplace()` can also be used to decrypt. 104 | pub fn stream_xor_inplace(m: &mut [u8], 105 | &Nonce(ref n): &Nonce, 106 | &Key(ref k): &Key) { 107 | unsafe { 108 | let _todo_use_result = $xor_name(m.as_mut_ptr(), 109 | m.as_ptr(), 110 | m.len() as c_ulonglong, 111 | n.as_ptr(), 112 | k.as_ptr()); 113 | } 114 | } 115 | 116 | /// `stream_xor_ic()` encrypts a message `m` using a secret key `k` and a nonce `n`, 117 | /// it is similar to `stream_xor()` but allows the caller to set the value of the initial 118 | /// block counter `ic`. 119 | /// 120 | /// `stream_xor()` guarantees that the ciphertext has the same length as the plaintext, 121 | /// and is the plaintext xor the output of `stream()`. 122 | /// Consequently `stream_xor()` can also be used to decrypt. 123 | pub fn stream_xor_ic(m: &[u8], 124 | &Nonce(ref n): &Nonce, 125 | ic: u64, 126 | &Key(ref k): &Key) -> Vec { 127 | unsafe { 128 | let mut c = vec![0u8; m.len()]; 129 | let _ = $xor_ic_name(c.as_mut_ptr(), 130 | m.as_ptr(), 131 | m.len() as c_ulonglong, 132 | n.as_ptr(), 133 | ic, 134 | k.as_ptr()); 135 | c 136 | } 137 | } 138 | 139 | /// `stream_xor_ic_inplace()` encrypts a message `m` using a secret key `k` and a nonce `n`, 140 | /// it is similar to `stream_xor_inplace()` but allows the caller to set the value of the initial 141 | /// block counter `ic`. 142 | /// The `stream_xor_ic_inplace()` function encrypts the message in place. 143 | /// 144 | /// `stream_xor_ic_inplace()` guarantees that the ciphertext has the same length as 145 | /// the plaintext, and is the plaintext xor the output of `stream_inplace()`. 146 | /// Consequently `stream_xor_ic_inplace()` can also be used to decrypt. 147 | pub fn stream_xor_ic_inplace(m: &mut [u8], 148 | &Nonce(ref n): &Nonce, 149 | ic: u64, 150 | &Key(ref k): &Key) { 151 | unsafe { 152 | let _ = $xor_ic_name(m.as_mut_ptr(), 153 | m.as_ptr(), 154 | m.len() as c_ulonglong, 155 | n.as_ptr(), 156 | ic, 157 | k.as_ptr()); 158 | } 159 | } 160 | 161 | 162 | #[cfg(test)] 163 | mod test_m { 164 | use super::*; 165 | 166 | #[test] 167 | fn test_encrypt_decrypt() { 168 | use crate::randombytes::randombytes; 169 | unwrap!(crate::init()); 170 | for i in 0..1024usize { 171 | let k = gen_key(); 172 | let n = gen_nonce(); 173 | let m = randombytes(i); 174 | let c = stream_xor(&m, &n, &k); 175 | let m2 = stream_xor(&c, &n, &k); 176 | assert!(m == m2); 177 | } 178 | } 179 | 180 | #[test] 181 | fn test_stream_xor() { 182 | use crate::randombytes::randombytes; 183 | unwrap!(crate::init()); 184 | for i in 0..1024usize { 185 | let k = gen_key(); 186 | let n = gen_nonce(); 187 | let m = randombytes(i); 188 | let mut c = m.clone(); 189 | let s = stream(c.len(), &n, &k); 190 | for (e, v) in c.iter_mut().zip(s.iter()) { 191 | *e ^= *v; 192 | } 193 | let c2 = stream_xor(&m, &n, &k); 194 | assert!(c == c2); 195 | } 196 | } 197 | 198 | #[test] 199 | fn test_stream_xor_inplace() { 200 | use crate::randombytes::randombytes; 201 | unwrap!(crate::init()); 202 | for i in 0..1024usize { 203 | let k = gen_key(); 204 | let n = gen_nonce(); 205 | let mut m = randombytes(i); 206 | let mut c = m.clone(); 207 | let s = stream(c.len(), &n, &k); 208 | for (e, v) in c.iter_mut().zip(s.iter()) { 209 | *e ^= *v; 210 | } 211 | stream_xor_inplace(&mut m, &n, &k); 212 | assert!(c == m); 213 | } 214 | } 215 | 216 | #[test] 217 | fn test_stream_xor_ic_same() { 218 | use crate::randombytes::randombytes; 219 | unwrap!(crate::init()); 220 | for i in 0..1024usize { 221 | let k = gen_key(); 222 | let n = gen_nonce(); 223 | let m = randombytes(i); 224 | let c = stream_xor(&m, &n, &k); 225 | let c_ic = stream_xor_ic(&m, &n, 0, &k); 226 | assert_eq!(c, c_ic); 227 | } 228 | } 229 | 230 | #[test] 231 | fn test_stream_xor_ic_inplace() { 232 | use crate::randombytes::randombytes; 233 | unwrap!(crate::init()); 234 | for i in 0..1024usize { 235 | let k = gen_key(); 236 | let n = gen_nonce(); 237 | for j in 0..10 { 238 | let mut m = randombytes(i); 239 | let c = stream_xor_ic(&m, &n, j, &k); 240 | stream_xor_ic_inplace(&mut m, &n, j, &k); 241 | assert_eq!(m, c); 242 | } 243 | } 244 | } 245 | 246 | #[test] 247 | fn test_serialisation() { 248 | use crate::test_utils::round_trip; 249 | unwrap!(crate::init()); 250 | for _ in 0..1024usize { 251 | let k = gen_key(); 252 | let n = gen_nonce(); 253 | round_trip(&k); 254 | round_trip(&n); 255 | } 256 | } 257 | } 258 | 259 | #[cfg(feature = "benchmarks")] 260 | #[cfg(test)] 261 | mod bench_m { 262 | extern crate test; 263 | use super::*; 264 | 265 | const BENCH_SIZES: [usize; 14] = [0, 1, 2, 4, 8, 16, 32, 64, 266 | 128, 256, 512, 1024, 2048, 4096]; 267 | 268 | #[bench] 269 | fn bench_stream(b: &mut test::Bencher) { 270 | unwrap!(crate::init()); 271 | let k = gen_key(); 272 | let n = gen_nonce(); 273 | b.iter(|| { 274 | for size in BENCH_SIZES.iter() { 275 | stream(*size, &n, &k); 276 | } 277 | }); 278 | } 279 | } 280 | 281 | )); 282 | -------------------------------------------------------------------------------- /src/crypto/stream/xchacha20.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! `xchacha20`. The same construction as `xsalsa20` but using 11 | //! `chacha20` instead of `salsa20` as the underlying stream cipher. 12 | //! This cipher is conjectured to meet the standard notion of 13 | //! unpredictability. 14 | 15 | use crate::ffi::{ 16 | crypto_stream_xchacha20, crypto_stream_xchacha20_KEYBYTES, crypto_stream_xchacha20_NONCEBYTES, 17 | crypto_stream_xchacha20_xor, crypto_stream_xchacha20_xor_ic, 18 | }; 19 | 20 | stream_module!( 21 | crypto_stream_xchacha20, 22 | crypto_stream_xchacha20_xor, 23 | crypto_stream_xchacha20_xor_ic, 24 | crypto_stream_xchacha20_KEYBYTES as usize, 25 | crypto_stream_xchacha20_NONCEBYTES as usize 26 | ); 27 | -------------------------------------------------------------------------------- /src/crypto/stream/xsalsa20.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! `crypto_stream_xsalsa20`, a particular cipher specified in 11 | //! [Cryptography in `NaCl`](http://nacl.cr.yp.to/valid.html), Section 7. 12 | //! This cipher is conjectured to meet the standard notion of 13 | //! unpredictability. 14 | 15 | use crate::ffi::{ 16 | crypto_stream_xsalsa20, crypto_stream_xsalsa20_KEYBYTES, crypto_stream_xsalsa20_NONCEBYTES, 17 | crypto_stream_xsalsa20_xor, crypto_stream_xsalsa20_xor_ic, 18 | }; 19 | 20 | stream_module!( 21 | crypto_stream_xsalsa20, 22 | crypto_stream_xsalsa20_xor, 23 | crypto_stream_xsalsa20_xor_ic, 24 | crypto_stream_xsalsa20_KEYBYTES as usize, 25 | crypto_stream_xsalsa20_NONCEBYTES as usize 26 | ); 27 | 28 | #[cfg(test)] 29 | #[rustfmt::skip] 30 | mod test { 31 | use super::*; 32 | 33 | #[test] 34 | fn test_vector_1() { 35 | // corresponding to tests/stream.c and tests/stream5.cpp from NaCl 36 | use crate::crypto::hash::sha256::{Digest, hash}; 37 | unwrap!(crate::init()); 38 | let firstkey = Key([0x1b, 0x27, 0x55, 0x64, 0x73, 0xe9, 0x85, 0xd4, 0x62, 0xcd, 0x51, 39 | 0x19, 0x7a, 0x9a, 0x46, 0xc7, 0x60, 0x09, 0x54, 0x9e, 0xac, 0x64, 40 | 0x74, 0xf2, 0x06, 0xc4, 0xee, 0x08, 0x44, 0xf6, 0x83, 0x89]); 41 | let nonce = Nonce([0x69, 0x69, 0x6e, 0xe9, 0x55, 0xb6, 0x2b, 0x73, 0xcd, 0x62, 0xbd, 42 | 0xa8, 0x75, 0xfc, 0x73, 0xd6, 0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 43 | 0x0b, 0x37]); 44 | let output = stream(0x40_0000, &nonce, &firstkey); 45 | let digest_expected = [0x66, 0x2b, 0x9d, 0x0e, 0x34, 0x63, 0x02, 0x91, 0x56, 0x06, 0x9b, 46 | 0x12, 0xf9, 0x18, 0x69, 0x1a, 0x98, 0xf7, 0xdf, 0xb2, 0xca, 0x03, 47 | 0x93, 0xc9, 0x6b, 0xbf, 0xc6, 0xb1, 0xfb, 0xd6, 0x30, 0xa2]; 48 | let Digest(digest) = hash(&output); 49 | assert!(digest == digest_expected); 50 | 51 | } 52 | 53 | #[test] 54 | fn test_vector_2() { 55 | // corresponding to tests/stream3.c and tests/stream7.cpp from NaCl 56 | unwrap!(crate::init()); 57 | let firstkey = Key([0x1b, 0x27, 0x55, 0x64, 0x73, 0xe9, 0x85, 0xd4, 0x62, 0xcd, 0x51, 58 | 0x19, 0x7a, 0x9a, 0x46, 0xc7, 0x60, 0x09, 0x54, 0x9e, 0xac, 0x64, 59 | 0x74, 0xf2, 0x06, 0xc4, 0xee, 0x08, 0x44, 0xf6, 0x83, 0x89]); 60 | let nonce = Nonce([0x69, 0x69, 0x6e, 0xe9, 0x55, 0xb6, 0x2b, 0x73, 0xcd, 0x62, 0xbd, 61 | 0xa8, 0x75, 0xfc, 0x73, 0xd6, 0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 62 | 0x0b, 0x37]); 63 | let rs = stream(32, &nonce, &firstkey); 64 | let rs_expected = vec![0xee, 0xa6, 0xa7, 0x25, 0x1c, 0x1e, 0x72, 0x91, 0x6d, 0x11, 0xc2, 65 | 0xcb, 0x21, 0x4d, 0x3c, 0x25, 0x25, 0x39, 0x12, 0x1d, 0x8e, 0x23, 66 | 0x4e, 0x65, 0x2d, 0x65, 0x1f, 0xa4, 0xc8, 0xcf, 0xf8, 0x80]; 67 | assert!(rs == rs_expected); 68 | } 69 | 70 | #[test] 71 | fn test_vector_3() { 72 | // corresponding to tests/stream4.c and tests/stream8.cpp from NaCl 73 | unwrap!(crate::init()); 74 | let firstkey = Key([0x1b, 0x27, 0x55, 0x64, 0x73, 0xe9, 0x85, 0xd4, 0x62, 0xcd, 0x51, 75 | 0x19, 0x7a, 0x9a, 0x46, 0xc7, 0x60, 0x09, 0x54, 0x9e, 0xac, 0x64, 76 | 0x74, 0xf2, 0x06, 0xc4, 0xee, 0x08, 0x44, 0xf6, 0x83, 0x89]); 77 | let nonce = Nonce([0x69, 0x69, 0x6e, 0xe9, 0x55, 0xb6, 0x2b, 0x73, 0xcd, 0x62, 0xbd, 78 | 0xa8, 0x75, 0xfc, 0x73, 0xd6, 0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 79 | 0x0b, 0x37]); 80 | let m = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81 | 0, 0, 0, 0, 0, 0xbe, 0x07, 0x5f, 0xc5, 0x3c, 0x81, 0xf2, 0xd5, 0xcf, 0x14, 0x13, 82 | 0x16, 0xeb, 0xeb, 0x0c, 0x7b, 0x52, 0x28, 0xc5, 0x2a, 0x4c, 0x62, 0xcb, 0xd4, 83 | 0x4b, 0x66, 0x84, 0x9b, 0x64, 0x24, 0x4f, 0xfc, 0xe5, 0xec, 0xba, 0xaf, 0x33, 84 | 0xbd, 0x75, 0x1a, 0x1a, 0xc7, 0x28, 0xd4, 0x5e, 0x6c, 0x61, 0x29, 0x6c, 0xdc, 85 | 0x3c, 0x01, 0x23, 0x35, 0x61, 0xf4, 0x1d, 0xb6, 0x6c, 0xce, 0x31, 0x4a, 0xdb, 86 | 0x31, 0x0e, 0x3b, 0xe8, 0x25, 0x0c, 0x46, 0xf0, 0x6d, 0xce, 0xea, 0x3a, 0x7f, 87 | 0xa1, 0x34, 0x80, 0x57, 0xe2, 0xf6, 0x55, 0x6a, 0xd6, 0xb1, 0x31, 0x8a, 0x02, 88 | 0x4a, 0x83, 0x8f, 0x21, 0xaf, 0x1f, 0xde, 0x04, 0x89, 0x77, 0xeb, 0x48, 0xf5, 89 | 0x9f, 0xfd, 0x49, 0x24, 0xca, 0x1c, 0x60, 0x90, 0x2e, 0x52, 0xf0, 0xa0, 0x89, 90 | 0xbc, 0x76, 0x89, 0x70, 0x40, 0xe0, 0x82, 0xf9, 0x37, 0x76, 0x38, 0x48, 0x64, 91 | 0x5e, 0x07, 0x05]; 92 | 93 | let c = stream_xor(m, &nonce, &firstkey); 94 | let c_expected = [0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73, 0xc2, 0x96, 0x50, 0xba, 95 | 0x32, 0xfc, 0x76, 0xce, 0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4, 96 | 0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a, 0xc0, 0xdf, 0xc1, 0x7c, 97 | 0x98, 0xdc, 0xe8, 0x7b, 0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72, 98 | 0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2, 0x27, 0x0d, 0x6f, 0xb8, 99 | 0x63, 0xd5, 0x17, 0x38, 0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a, 100 | 0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae, 0x90, 0x22, 0x43, 0x68, 101 | 0x51, 0x7a, 0xcf, 0xea, 0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda, 102 | 0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde, 0x56, 0x24, 0x4a, 0x9e, 103 | 0x88, 0xd5, 0xf9, 0xb3, 0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6, 104 | 0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74, 0xe3, 0x55, 0xa5]; 105 | assert!(c[32..] == c_expected[..]); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/crypto/verify.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Constant-time comparison of fixed-size vecs 11 | 12 | use crate::ffi; 13 | 14 | /// `verify_16()` returns `true` if `x[0]`, `x[1]`, ..., `x[15]` are the 15 | /// same as `y[0]`, `y[1]`, ..., `y[15]`. Otherwise it returns `false`. 16 | /// 17 | /// This function is safe to use for secrets `x[0]`, `x[1]`, ..., `x[15]`, 18 | /// `y[0]`, `y[1]`, ..., `y[15]`. The time taken by `verify_16` is independent 19 | /// of the contents of `x[0]`, `x[1]`, ..., `x[15]`, `y[0]`, `y[1]`, ..., `y[15]`. 20 | /// In contrast, the standard C comparison function `memcmp(x,y,16)` takes time 21 | /// that depends on the longest matching prefix of `x` and `y`, often allowing easy 22 | /// timing attacks. 23 | pub fn verify_16(x: &[u8; 16], y: &[u8; 16]) -> bool { 24 | unsafe { ffi::crypto_verify_16(x as *const u8, y as *const u8) == 0 } 25 | } 26 | 27 | /// `verify_32()` returns true if `x[0]`, `x[1]`, ..., `x[31]` are the 28 | /// same as `y[0]`, `y[1]`, ..., `y[31]`. Otherwise it returns `false`. 29 | /// 30 | /// This function is safe to use for secrets `x[0]`, `x[1]`, ..., `x[31]`, 31 | /// `y[0]`, `y[1]`, ..., `y[31]`. The time taken by `verify_32` is independent 32 | /// of the contents of `x[0]`, `x[1]`, ..., `x[31]`, `y[0]`, `y[1]`, ..., `y[31]`. 33 | /// In contrast, the standard C comparison function `memcmp(x,y,32)` takes time 34 | /// that depends on the longest matching prefix of `x` and `y`, often allowing easy 35 | /// timing attacks. 36 | pub fn verify_32(x: &[u8; 32], y: &[u8; 32]) -> bool { 37 | unsafe { ffi::crypto_verify_32(x as *const u8, y as *const u8) == 0 } 38 | } 39 | 40 | /// `verify_64()` returns true if `x[0]`, `x[1]`, ..., `x[63]` are the 41 | /// same as `y[0]`, `y[1]`, ..., `y[63]`. Otherwise it returns `false`. 42 | /// 43 | /// This function is safe to use for secrets `x[0]`, `x[1]`, ..., `x[63]`, 44 | /// `y[0]`, `y[1]`, ..., `y[63]`. The time taken by `verify_64` is independent 45 | /// of the contents of `x[0]`, `x[1]`, ..., `x[63]`, `y[0]`, `y[1]`, ..., `y[63]`. 46 | /// In contrast, the standard C comparison function `memcmp(x,y,64)` takes time 47 | /// that depends on the longest matching prefix of `x` and `y`, often allowing easy 48 | /// timing attacks. 49 | pub fn verify_64(x: &[u8; 64], y: &[u8; 64]) -> bool { 50 | unsafe { ffi::crypto_verify_64(x as *const u8, y as *const u8) == 0 } 51 | } 52 | 53 | #[cfg(test)] 54 | mod test { 55 | use super::*; 56 | 57 | #[test] 58 | fn test_verify_16() { 59 | use crate::randombytes::randombytes_into; 60 | 61 | unwrap!(crate::init()); 62 | for _ in 0usize..256 { 63 | let mut x = [0; 16]; 64 | let mut y = [0; 16]; 65 | assert!(verify_16(&x, &y)); 66 | randombytes_into(&mut x); 67 | randombytes_into(&mut y); 68 | if x == y { 69 | assert!(verify_16(&x, &y)) 70 | } else { 71 | assert!(!verify_16(&x, &y)) 72 | } 73 | } 74 | } 75 | 76 | #[test] 77 | fn test_verify_32() { 78 | use crate::randombytes::randombytes_into; 79 | 80 | unwrap!(crate::init()); 81 | for _ in 0usize..256 { 82 | let mut x = [0; 32]; 83 | let mut y = [0; 32]; 84 | assert!(verify_32(&x, &y)); 85 | randombytes_into(&mut x); 86 | randombytes_into(&mut y); 87 | if x == y { 88 | assert!(verify_32(&x, &y)) 89 | } else { 90 | assert!(!verify_32(&x, &y)) 91 | } 92 | } 93 | } 94 | 95 | #[test] 96 | fn test_verify_64() { 97 | use crate::randombytes::randombytes_into; 98 | 99 | unwrap!(crate::init()); 100 | for _ in 0usize..256 { 101 | let mut x = [0; 64]; 102 | let mut y = [0; 64]; 103 | assert!(verify_64(&x, &y)); 104 | randombytes_into(&mut x); 105 | randombytes_into(&mut y); 106 | if x[..] == y[..] { 107 | assert!(verify_64(&x, &y)) 108 | } else { 109 | assert!(!verify_64(&x, &y)) 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Rust bindings to the [sodium library](https://github.com/jedisct1/libsodium). 11 | //! 12 | //! Sodium is a portable implementation of Dan Bernsteins [`NaCl`: Networking and 13 | //! Cryptography library](http://nacl.cr.yp.to). 14 | //! 15 | //! For details on building rust_sodium, see 16 | //! [the README](https://github.com/maidsafe/rust_sodium/blob/master/README.md). 17 | //! 18 | //! For most users, if you want public-key (asymmetric) cryptography you should use 19 | //! the functions in [`crypto::box_`](crypto/box_/index.html) for encryption/decryption. 20 | //! 21 | //! If you want secret-key (symmetric) cryptography you should be using the 22 | //! functions in [`crypto::secretbox`](crypto/secretbox/index.html) for encryption/decryption. 23 | //! 24 | //! For public-key signatures you should use the functions in 25 | //! [`crypto::sign`](crypto/sign/index.html) for signature creation and verification. 26 | //! 27 | //! Unless you know what you're doing you most certainly don't want to use the 28 | //! functions in [`crypto::scalarmult`](crypto/scalarmult/index.html), 29 | //! [`crypto::stream`](crypto/stream/index.html), [`crypto::auth`](crypto/auth/index.html) and 30 | //! [`crypto::onetimeauth`](crypto/onetimeauth/index.html). 31 | //! 32 | //! ## Thread Safety 33 | //! All functions in this library are thread-safe provided that the [`init()`](fn.init.html) 34 | //! function has been called during program execution. 35 | //! 36 | //! If [`init()`](fn.init.html) hasn't been called then all functions except the random-number 37 | //! generation functions and the key-generation functions are thread-safe. 38 | //! 39 | //! # Public-key cryptography 40 | //! [`crypto::box_`](crypto/box_/index.html) 41 | //! 42 | //! [`crypto::sign`](crypto/sign/index.html) 43 | //! 44 | //! # Sealed boxes 45 | //! [`crypto::sealedbox`](crypto/sealedbox/index.html) 46 | //! 47 | //! # Secret-key cryptography 48 | //! [`crypto::secretbox`](crypto/secretbox/index.html) 49 | //! 50 | //! [`crypto::stream`](crypto/stream/index.html) 51 | //! 52 | //! [`crypto::auth`](crypto/auth/index.html) 53 | //! 54 | //! [`crypto::onetimeauth`](crypto/onetimeauth/index.html) 55 | //! 56 | //! # Low-level functions 57 | //! [`crypto::hash`](crypto/hash/index.html) 58 | //! 59 | //! [`crypto::verify`](crypto/verify/index.html) 60 | //! 61 | //! [`crypto::shorthash`](crypto/shorthash/index.html) 62 | 63 | #![doc( 64 | html_logo_url = "https://raw.githubusercontent.com/maidsafe/QA/master/Images/maidsafe_logo.png", 65 | html_favicon_url = "https://maidsafe.net/img/favicon.ico", 66 | test(attr(forbid(warnings))) 67 | )] 68 | // For explanation of lint checks, run `rustc -W help` or see 69 | // https://github.com/maidsafe/QA/blob/master/Documentation/Rust%20Lint%20Checks.md 70 | #![forbid( 71 | bad_style, 72 | exceeding_bitshifts, 73 | mutable_transmutes, 74 | no_mangle_const_items, 75 | unknown_crate_types, 76 | warnings 77 | )] 78 | #![deny( 79 | deprecated, 80 | improper_ctypes, 81 | missing_docs, 82 | non_shorthand_field_patterns, 83 | overflowing_literals, 84 | plugin_as_library, 85 | stable_features, 86 | unconditional_recursion, 87 | unknown_lints, 88 | unused, 89 | unused_allocation, 90 | unused_attributes, 91 | unused_comparisons, 92 | unused_features, 93 | unused_parens, 94 | while_true 95 | )] 96 | #![warn( 97 | trivial_numeric_casts, 98 | unused_extern_crates, 99 | unused_import_braces, 100 | unused_qualifications, 101 | unused_results 102 | )] 103 | // Allow `trivial_casts` to cast `u8` to `c_char`, which is `u8` or `i8`, depending on the 104 | // architecture. 105 | #![allow( 106 | box_pointers, 107 | missing_copy_implementations, 108 | missing_debug_implementations, 109 | trivial_casts, 110 | unsafe_code, 111 | variant_size_differences 112 | )] 113 | 114 | #[cfg(test)] 115 | extern crate hex; 116 | #[cfg(test)] 117 | extern crate rmp_serde; 118 | #[cfg(test)] 119 | extern crate serde_json; 120 | #[macro_use] 121 | extern crate unwrap; 122 | 123 | use rust_sodium_sys as ffi; 124 | 125 | #[macro_use] 126 | mod newtype_macros; 127 | pub mod randombytes; 128 | pub mod utils; 129 | pub mod version; 130 | 131 | #[cfg(test)] 132 | mod test_utils; 133 | 134 | /// Cryptographic functions 135 | pub mod crypto { 136 | pub mod aead; 137 | pub mod auth; 138 | pub mod box_; 139 | pub mod hash; 140 | pub mod kx; 141 | pub mod onetimeauth; 142 | pub mod pwhash; 143 | pub mod scalarmult; 144 | pub mod sealedbox; 145 | pub mod secretbox; 146 | pub mod shorthash; 147 | pub mod sign; 148 | pub mod stream; 149 | pub mod verify; 150 | } 151 | 152 | /// Initialises libsodium and chooses faster versions of the primitives if possible. Also makes the 153 | /// random number generation functions (`gen_key`, `gen_keypair`, `gen_nonce`, `randombytes`, 154 | /// `randombytes_into`) thread-safe. 155 | /// 156 | /// `init()` returns `Ok` if initialisation succeeded and `Err` if it failed. 157 | pub fn init() -> Result<(), ()> { 158 | if unsafe { ffi::sodium_init() } >= 0 { 159 | Ok(()) 160 | } else { 161 | Err(()) 162 | } 163 | } 164 | 165 | #[allow(clippy::doc_markdown)] 166 | /// Sets [libsodium's `randombytes_implementation`] 167 | /// (https://download.libsodium.org/doc/advanced/custom_rng.html) to use a 168 | /// [Rust `Rng` implementation](../rand/trait.Rng.html) and initialises libsodium. 169 | /// See [the `rust_sodium-sys`' docs](../rust_sodium_sys/fn.init_with_rng.html) for further details. 170 | pub fn init_with_rng(rng: &mut T) -> Result<(), i32> { 171 | ffi::init_with_rng(rng) 172 | } 173 | -------------------------------------------------------------------------------- /src/randombytes.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Cryptographic random number generation. 11 | 12 | use crate::ffi; 13 | use libc::c_void; 14 | 15 | /// `randombytes()` randomly generates size bytes of data. 16 | /// 17 | /// THREAD SAFETY: `randombytes()` is thread-safe provided that you have 18 | /// called `rust_sodium::init()` once before using any other function 19 | /// from `rust_sodium`. 20 | pub fn randombytes(size: usize) -> Vec { 21 | unsafe { 22 | let mut buf = vec![0u8; size]; 23 | let pbuf = buf.as_mut_ptr() as *mut c_void; 24 | ffi::randombytes_buf(pbuf, size); 25 | buf 26 | } 27 | } 28 | 29 | /// `randombytes_into()` fills a buffer `buf` with random data. 30 | /// 31 | /// THREAD SAFETY: `randombytes_into()` is thread-safe provided that you have 32 | /// called `rust_sodium::init()` once before using any other function 33 | /// from `rust_sodium`. 34 | pub fn randombytes_into(buf: &mut [u8]) { 35 | unsafe { 36 | ffi::randombytes_buf(buf.as_mut_ptr() as *mut c_void, buf.len()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test_utils.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | use rmp_serde; 11 | use serde::de::DeserializeOwned; 12 | use serde::{Deserialize, Serialize}; 13 | use serde_json; 14 | 15 | // Encodes then decodes `value` using JSON 16 | pub fn round_trip(value: &T) 17 | where 18 | T: Serialize + DeserializeOwned + Eq + ::std::fmt::Debug, 19 | { 20 | let encoded_value = unwrap!(serde_json::to_string(value)); 21 | let decoded_value: T = unwrap!(serde_json::from_str(&encoded_value)); 22 | assert_eq!(*value, decoded_value); 23 | 24 | let mut buf = Vec::new(); 25 | unwrap!(value.serialize(&mut rmp_serde::Serializer::new(&mut buf))); 26 | let mut de = rmp_serde::Deserializer::new(&buf[..]); 27 | let decoded_value: T = unwrap!(Deserialize::deserialize(&mut de)); 28 | assert_eq!(*value, decoded_value); 29 | } 30 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Libsodium utility functions 11 | 12 | use crate::ffi; 13 | use libc::c_void; 14 | 15 | /// `memzero()` tries to effectively zero out the data in `x` even if 16 | /// optimizations are being applied to the code. 17 | pub fn memzero(x: &mut [u8]) { 18 | unsafe { 19 | ffi::sodium_memzero(x.as_mut_ptr() as *mut c_void, x.len()); 20 | } 21 | } 22 | 23 | /// `memcmp()` returns true if `x[0]`, `x[1]`, ..., `x[len-1]` are the 24 | /// same as `y[0]`, `y[1]`, ..., `y[len-1]`. Otherwise it returns `false`. 25 | /// 26 | /// This function is safe to use for secrets `x[0]`, `x[1]`, ..., `x[len-1]`, 27 | /// `y[0]`, `y[1]`, ..., `y[len-1]`. The time taken by `memcmp` is independent 28 | /// of the contents of `x[0]`, `x[1]`, ..., `x[len-1]`, `y[0]`, `y[1]`, ..., `y[len-1]`. 29 | /// In contrast, the standard C comparison function `memcmp(x,y,len)` takes time 30 | /// that depends on the longest matching prefix of `x` and `y`, often allowing easy 31 | /// timing attacks. 32 | pub fn memcmp(x: &[u8], y: &[u8]) -> bool { 33 | if x.len() != y.len() { 34 | return false; 35 | } 36 | unsafe { 37 | ffi::sodium_memcmp( 38 | x.as_ptr() as *mut c_void, 39 | y.as_ptr() as *mut c_void, 40 | x.len(), 41 | ) == 0 42 | } 43 | } 44 | 45 | /// `increment_le()` treats `x` as an unsigned little-endian number and increments it. 46 | /// 47 | /// WARNING: this method does not check for arithmetic overflow. When used for incrementing 48 | /// nonces it is the callers responsibility to ensure that any given nonce value 49 | /// is only used once. 50 | /// If the caller does not do that the cryptographic primitives in `rust_sodium` 51 | /// will not uphold any security guarantees (i.e. they will break) 52 | pub fn increment_le(x: &mut [u8]) { 53 | unsafe { 54 | ffi::sodium_increment(x.as_mut_ptr(), x.len()); 55 | } 56 | } 57 | 58 | /// Tries to add padding to a sequence of bytes. 59 | /// If the block size is zero, or the padded buffer's length 60 | /// could overflow `usize`, this function returns `Err`. 61 | /// Otherwise, it returns `Ok` wrapping the padded byte array. 62 | pub fn pad(mut buf: Vec, blocksize: usize) -> Result, ()> { 63 | let unpadded_buflen = buf.len(); 64 | let max_buflen = unpadded_buflen + blocksize; 65 | let mut padded_buflen = 0; 66 | 67 | if max_buflen <= unpadded_buflen { 68 | return Err(()); 69 | } 70 | 71 | // extend with zeroes 72 | buf.resize(max_buflen, 0); 73 | 74 | let error = unsafe { 75 | ffi::sodium_pad( 76 | &mut padded_buflen, 77 | buf.as_mut_ptr(), 78 | unpadded_buflen, 79 | blocksize, 80 | max_buflen, 81 | ) 82 | }; 83 | 84 | assert!(error == 0, "sodium_pad: unsatisfied precondition?!"); 85 | assert!(padded_buflen <= max_buflen, "math is broken?!"); 86 | assert!(padded_buflen > unpadded_buflen, "no padding added?!"); 87 | 88 | buf.truncate(padded_buflen); 89 | 90 | Ok(buf) 91 | } 92 | 93 | /// Attempts to remove padding from a byte sequence created via `pad()`. 94 | /// If the padding is nonexistent, invalid, or the block size does not 95 | /// match the `blocksize` argument of `pad()`, this returns `Err`. 96 | pub fn unpad(buf: &[u8], blocksize: usize) -> Result<&[u8], ()> { 97 | let padded_buflen = buf.len(); 98 | let mut unpadded_buflen = 0; 99 | 100 | let error = 101 | unsafe { ffi::sodium_unpad(&mut unpadded_buflen, buf.as_ptr(), padded_buflen, blocksize) }; 102 | 103 | if error != 0 { 104 | return Err(()); 105 | } 106 | 107 | assert!(unpadded_buflen < padded_buflen, "no padding?!"); 108 | 109 | Ok(&buf[..unpadded_buflen]) 110 | } 111 | 112 | #[cfg(test)] 113 | mod test { 114 | use super::*; 115 | 116 | #[test] 117 | fn test_memcmp() { 118 | use crate::randombytes::randombytes; 119 | 120 | unwrap!(crate::init()); 121 | for i in 0usize..256 { 122 | let x = randombytes(i); 123 | assert!(memcmp(&x, &x)); 124 | let mut y = x.clone(); 125 | assert!(memcmp(&x, &y)); 126 | y.push(0); 127 | assert!(!memcmp(&x, &y)); 128 | assert!(!memcmp(&y, &x)); 129 | 130 | y = randombytes(i); 131 | if x == y { 132 | assert!(memcmp(&x, &y)) 133 | } else { 134 | assert!(!memcmp(&x, &y)) 135 | } 136 | } 137 | } 138 | 139 | #[test] 140 | fn test_increment_le_zero() { 141 | unwrap!(crate::init()); 142 | for i in 1usize..256 { 143 | let mut x = vec![0u8; i]; 144 | increment_le(&mut x); 145 | assert!(!x.iter().all(|x| *x == 0)); 146 | let mut y = vec![0u8; i]; 147 | y[0] += 1; 148 | assert_eq!(x, y); 149 | } 150 | } 151 | 152 | #[test] 153 | fn test_increment_le_vectors() { 154 | unwrap!(crate::init()); 155 | let mut x = [255, 2, 3, 4, 5]; 156 | let y = [0, 3, 3, 4, 5]; 157 | increment_le(&mut x); 158 | assert!(!x.iter().all(|x| *x == 0)); 159 | assert_eq!(x, y); 160 | let mut x = [255, 255, 3, 4, 5]; 161 | let y = [0, 0, 4, 4, 5]; 162 | increment_le(&mut x); 163 | assert!(!x.iter().all(|x| *x == 0)); 164 | assert_eq!(x, y); 165 | let mut x = [255, 255, 255, 4, 5]; 166 | let y = [0, 0, 0, 5, 5]; 167 | increment_le(&mut x); 168 | assert!(!x.iter().all(|x| *x == 0)); 169 | assert_eq!(x, y); 170 | let mut x = [255, 255, 255, 255, 5]; 171 | let y = [0, 0, 0, 0, 6]; 172 | increment_le(&mut x); 173 | assert!(!x.iter().all(|x| *x == 0)); 174 | assert_eq!(x, y); 175 | let mut x = [255, 255, 255, 255, 255]; 176 | let y = [0, 0, 0, 0, 0]; 177 | increment_le(&mut x); 178 | assert!(x.iter().all(|x| *x == 0)); 179 | assert_eq!(x, y); 180 | } 181 | 182 | #[test] 183 | fn test_increment_le_overflow() { 184 | unwrap!(crate::init()); 185 | for i in 1usize..256 { 186 | let mut x = vec![255u8; i]; 187 | increment_le(&mut x); 188 | assert!(x.iter().all(|xi| *xi == 0)); 189 | } 190 | } 191 | 192 | #[test] 193 | fn test_padding_not_multiple_of_blocksize() { 194 | unwrap!(crate::init()); 195 | let v = vec![1, 2, 3, 4, 5, 6, 7]; 196 | let p = unwrap!(pad(v.clone(), 5)); 197 | let u = unwrap!(unpad(&p, 5)); 198 | 199 | assert!(p.len() == 10); 200 | assert!(u == &v[..]); 201 | } 202 | 203 | #[test] 204 | fn test_padding_multiple_of_blocksize() { 205 | unwrap!(crate::init()); 206 | let v = vec![1, 2, 3, 4, 5, 6]; 207 | let p = unwrap!(pad(v.clone(), 3)); 208 | let u = unwrap!(unpad(&p, 3)); 209 | 210 | assert!(p.len() == 9); 211 | assert!(u == &v[..]); 212 | } 213 | 214 | #[test] 215 | fn test_padding_not_multiple_of_blocksize_pow2() { 216 | unwrap!(crate::init()); 217 | let v = vec![1, 2, 3, 4, 5, 6, 7]; 218 | let p = unwrap!(pad(v.clone(), 4)); 219 | let u = unwrap!(unpad(&p, 4)); 220 | 221 | assert!(p.len() == 8); 222 | assert!(u == &v[..]); 223 | } 224 | 225 | #[test] 226 | fn test_padding_multiple_of_blocksize_pow2() { 227 | unwrap!(crate::init()); 228 | let v = vec![1, 2, 3, 4, 5, 6, 7, 8]; 229 | let p = unwrap!(pad(v.clone(), 4)); 230 | let u = unwrap!(unpad(&p, 4)); 231 | 232 | assert!(p.len() == 12); 233 | assert!(u == &v[..]); 234 | } 235 | 236 | #[test] 237 | fn test_padding_invalid_block_size() { 238 | unwrap!(crate::init()); 239 | // invalid block size 240 | unwrap_err!(pad(Vec::new(), 0)); 241 | let v = vec![0x80]; 242 | unwrap_err!(unpad(&v, 0)); 243 | 244 | // mismatching block size 245 | let v = unwrap!(pad(Vec::new(), 8)); 246 | unwrap_err!(unpad(&v, 4)); 247 | } 248 | 249 | #[test] 250 | fn test_padding_invalid_padded_size() { 251 | unwrap!(crate::init()); 252 | // An empty array couldn't possibly have been created by `pad()`. 253 | unwrap_err!(unpad(&[], 1)); 254 | 255 | // Padded scheme is of incorrect length (not a multiple of block size) 256 | let mut v = unwrap!(pad(vec![42], 1337)); 257 | let _ = v.pop(); 258 | unwrap_err!(unpad(&v, 1337)); 259 | } 260 | 261 | #[test] 262 | fn test_padding_invalid_padded_data() { 263 | unwrap!(crate::init()); 264 | // A trailing padding byte is incorrect 265 | let mut v = unwrap!(pad(vec![42], 128)); 266 | *v.last_mut().expect("non-empty") = 99; 267 | unwrap_err!(unpad(&v, 128)); 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /src/version.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | //! Libsodium version functions 11 | 12 | use crate::ffi; 13 | use std::ffi::CStr; 14 | 15 | /// `version_string()` returns the version string from libsodium. 16 | pub fn version_string() -> &'static str { 17 | let version = unsafe { CStr::from_ptr(ffi::sodium_version_string()) }; 18 | unwrap!(version.to_str()) 19 | } 20 | 21 | /// `version_major()` returns the major version from libsodium. 22 | pub fn version_major() -> usize { 23 | unsafe { ffi::sodium_library_version_major() as usize } 24 | } 25 | 26 | /// `version_minor()` returns the minor version from libsodium. 27 | pub fn version_minor() -> usize { 28 | unsafe { ffi::sodium_library_version_minor() as usize } 29 | } 30 | 31 | #[cfg(test)] 32 | mod test { 33 | #[test] 34 | fn test_version_string() { 35 | use crate::version::version_string; 36 | unwrap!(crate::init()); 37 | assert!(!version_string().is_empty()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /systest/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["MaidSafe Developers "] 3 | build = "build.rs" 4 | description = "Test that bindings match native library's interface" 5 | edition = "2018" 6 | homepage = "https://maidsafe.net" 7 | license = "MIT OR Apache-2.0" 8 | name = "systest" 9 | publish = false 10 | version = "0.2.0" 11 | 12 | [dependencies] 13 | rust_sodium-sys = { path = "../rust_sodium-sys", version = "~0.10.1" } 14 | libc = "~0.2.38" 15 | 16 | [build-dependencies] 17 | ctest = "=0.1.4" 18 | unwrap = "~1.2.0" 19 | -------------------------------------------------------------------------------- /systest/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | extern crate ctest; 11 | #[macro_use] 12 | extern crate unwrap; 13 | 14 | use std::env; 15 | 16 | fn main() { 17 | let include = unwrap!(env::var("DEP_SODIUM_INCLUDE")); 18 | let mut cfg = ctest::TestGenerator::new(); 19 | 20 | cfg.header("sodium.h") 21 | .header("sodium/core.h") 22 | .header("sodium/crypto_aead_aes256gcm.h") 23 | .header("sodium/crypto_aead_chacha20poly1305.h") 24 | .header("sodium/crypto_aead_xchacha20poly1305.h") 25 | .header("sodium/crypto_auth.h") 26 | .header("sodium/crypto_auth_hmacsha256.h") 27 | .header("sodium/crypto_auth_hmacsha512256.h") 28 | .header("sodium/crypto_auth_hmacsha512.h") 29 | .header("sodium/crypto_box_curve25519xchacha20poly1305.h") 30 | .header("sodium/crypto_box_curve25519xsalsa20poly1305.h") 31 | .header("sodium/crypto_box.h") 32 | .header("sodium/crypto_core_ed25519.h") 33 | .header("sodium/crypto_core_hchacha20.h") 34 | .header("sodium/crypto_core_hsalsa20.h") 35 | .header("sodium/crypto_core_salsa2012.h") 36 | .header("sodium/crypto_core_salsa208.h") 37 | .header("sodium/crypto_core_salsa20.h") 38 | .header("sodium/crypto_generichash_blake2b.h") 39 | .header("sodium/crypto_generichash.h") 40 | .header("sodium/crypto_hash.h") 41 | .header("sodium/crypto_hash_sha256.h") 42 | .header("sodium/crypto_hash_sha512.h") 43 | .header("sodium/crypto_kdf_blake2b.h") 44 | .header("sodium/crypto_kdf.h") 45 | .header("sodium/crypto_kx.h") 46 | .header("sodium/crypto_onetimeauth.h") 47 | .header("sodium/crypto_onetimeauth_poly1305.h") 48 | .header("sodium/crypto_pwhash_argon2id.h") 49 | .header("sodium/crypto_pwhash_argon2i.h") 50 | .header("sodium/crypto_pwhash.h") 51 | .header("sodium/crypto_pwhash_scryptsalsa208sha256.h") 52 | .header("sodium/crypto_scalarmult_curve25519.h") 53 | .header("sodium/crypto_scalarmult_ed25519.h") 54 | .header("sodium/crypto_scalarmult.h") 55 | .header("sodium/crypto_secretbox.h") 56 | .header("sodium/crypto_secretbox_xchacha20poly1305.h") 57 | .header("sodium/crypto_secretbox_xsalsa20poly1305.h") 58 | .header("sodium/crypto_secretstream_xchacha20poly1305.h") 59 | .header("sodium/crypto_shorthash.h") 60 | .header("sodium/crypto_shorthash_siphash24.h") 61 | .header("sodium/crypto_sign_ed25519.h") 62 | .header("sodium/crypto_sign_edwards25519sha512batch.h") 63 | .header("sodium/crypto_sign.h") 64 | .header("sodium/crypto_stream_chacha20.h") 65 | .header("sodium/crypto_stream.h") 66 | .header("sodium/crypto_stream_salsa2012.h") 67 | .header("sodium/crypto_stream_salsa208.h") 68 | .header("sodium/crypto_stream_salsa20.h") 69 | .header("sodium/crypto_stream_xchacha20.h") 70 | .header("sodium/crypto_stream_xsalsa20.h") 71 | .header("sodium/crypto_verify_16.h") 72 | .header("sodium/crypto_verify_32.h") 73 | .header("sodium/crypto_verify_64.h") 74 | .header("sodium/export.h") 75 | .header("sodium/randombytes.h") 76 | .header("sodium/randombytes_salsa20_random.h") 77 | .header("sodium/randombytes_sysrandom.h") 78 | .header("sodium/runtime.h") 79 | .header("sodium/utils.h") 80 | .header("sodium/version.h"); 81 | cfg.include(&include); 82 | cfg.type_name(|s, _| s.to_string()); 83 | cfg.skip_field(|_, field| field.starts_with("__bindgen_padding_")); 84 | cfg.skip_type(|_| true); 85 | cfg.skip_const(|s| { 86 | s.ends_with("_PRIMITIVE") || s.ends_with("_STRPREFIX") || s == "SODIUM_VERSION_STRING" 87 | }); 88 | if cfg!(target_env = "msvc") { 89 | // Suppress "warning C4324: 'crypto_generichash_blake2b_state': structure was padded due to 90 | // alignment specifier" 91 | cfg.flag("/wd4324"); 92 | } 93 | cfg.generate("../rust_sodium-sys/src/lib.rs", "all.rs"); 94 | } 95 | -------------------------------------------------------------------------------- /systest/src/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | #![allow(bad_style)] 11 | 12 | extern crate rust_sodium_sys; 13 | extern crate libc; 14 | 15 | use libc::*; 16 | use rust_sodium_sys::*; 17 | 18 | include!(concat!(env!("OUT_DIR"), "/all.rs")); 19 | --------------------------------------------------------------------------------