1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
/*! This crate implements the Saber post-quantum key-encapsulation mechanism. [Saber][eprint] is a post-quantum cryptographic key-encapsulation mechanism. It has been devised by: - Jan-Pieter D'Anvers, KU Leuven, imec-COSIC - Angshuman Karmakar, KU Leuven, imec-COSIC - Sujoy Sinha Roy, KU Leuven, imec-COSIC - Frederik Vercauteren, KU Leuven, imec-COSIC Like many others, it is one of the round-2 candidates of the [NIST Post-Quantum Cryptography "competition"][nist]. # Getting started Install this crate using Cargo by adding it to your dependencies: ```toml [dependencies] saber = { git = "https://github.com/dsprenkels/saber-rust" } ``` Then, choose one of the parameter sets by importing them into your code: ```rust extern crate saber; use saber::saber::{keygen, encapsulate, decapsulate}; ``` Now you can use the functions [`keygen`], [`encapsulate`] and [`decapsulate`] to agree on a shared secret key between two endpoints. ```rust # extern crate saber; # use ::saber::saber::{keygen, encapsulate, decapsulate}; // Consider a server with a key pair let server_secret_key = keygen(); let server_public_key = server_secret_key.public_key(); // Let a client encapsulate some shared secret for the server let (client_secret, ciphertext) = encapsulate(&server_public_key); // Have the server decrypt the ciphertext let server_secret = decapsulate(&ciphertext, &server_secret_key); assert_eq!(client_secret.as_slice(), server_secret.as_slice()); ``` # (De)serializing keys Both [`PublicKey`] and [`SecretKey`] can be stored into arrays using [`PublicKey::to_bytes`] and [`SecretKey::to_bytes`] respectively. To load a key back from a `&[u8]` buffer, use [`PublicKey::from_bytes`] and [`SecretKey::from_bytes`]. For example: ```rust # let secret_key = ::saber::saber::keygen(); let public_key = secret_key.public_key(); use saber::saber::{PublicKey, encapsulate}; // Store the public key let public_key_bytes = public_key.to_bytes().into_bytes(); println!("Saber public key: {:02x?}", &public_key_bytes[..]); // Lose the original public-key struct drop(public_key); // Reload the public key let public_key = match PublicKey::from_bytes(&public_key_bytes) { Ok(pk) => pk, Err(err) => panic!("Error decoding public key: {}", err), }; // Now you can use the key again for key encapsulation let (client_secret, ciphertext) = encapsulate(&public_key); ``` [nist]: https://csrc.nist.gov/projects/post-quantum-cryptography/round-2-submissions [eprint]: https://eprint.iacr.org/2018/230.pdf [`keygen`]: saber/fn.keygen.html [`encapsulate`]: saber/fn.encapsulate.html [`decapsulate`]: saber/fn.decapsulate.html [`PublicKey`]: saber/struct.PublicKey.html [`SecretKey`]: saber/struct.SecretKey.html [`PublicKey::to_bytes`]: saber/struct.PublicKey.html#method.to_bytes [`SecretKey::to_bytes`]: saber/struct.SecretKey.html#method.to_bytes [`PublicKey::from_bytes`]: saber/saber/struct.PublicKey.html#method.from_bytes [`SecretKey::from_bytes`]: saber/saber/struct.SecretKey.html#method.from_bytes */ #![allow(clippy::suspicious_arithmetic_impl)] use core::fmt::Formatter; extern crate rand_os; extern crate secret_integers; extern crate sha3; #[macro_use] mod newtype; #[macro_use] mod params; #[macro_use] mod non_generic; mod generic; mod poly; pub mod saber; pub mod lightsaber; pub mod firesaber; /// Error type for the [saber crate]. /// /// [saber crate]: index.html #[derive(Clone, Debug)] pub enum Error { /// This error indicates that the length of a slice that was provided to some function was /// incorrect. /// /// For convenience, `BadLength` will be filled with some useful values. `name` contains /// the name of the slice that had an invalid length. It was expected to be `expected` items /// long, but the actual size was `actual`. BadLength { name: &'static str, actual: usize, expected: usize, }, #[doc(hidden)] __Nonexhaustive, } impl std::fmt::Display for Error { fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { match self { Error::BadLength { name, actual, expected, } => write!( f, "error: {} should be {} element long, not {}", name, expected, actual ), Error::__Nonexhaustive => { unreachable!("Error::__Nonexhaustive should never have been constructed") } } } } impl std::error::Error for Error {}