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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
//! This crate implements the NTRU encryption library in Rust. It is an interface to libntru, even //! though many of the methods are being implemented in pure Rust. The plan is to gradually //! implement the library natively. It uses this library since it has proven to be faster than the //! original NTRU encryption implementation. In any case, it is much faster than usual encryption / //! decryption mecanisms, and quantum-proof. More on NTRU encryption //! [here](https://en.wikipedia.org/wiki/NTRUEncrypt). //! //! To use it you only need to include the following in your crate: //! //! ``` //! extern crate ntru; //! ``` //! //! NTRU encryption uses its own keys, that must be generated with the included random key //! generator, and must not be used for other applications such as NTRU signing or NTRUNMLS. //! //! # Examples //! //! ``` //! use ntru::rand::RNG_DEFAULT; //! use ntru::encparams::DEFAULT_PARAMS_256_BITS; //! //! let rand_ctx = ntru::rand::init(&RNG_DEFAULT).unwrap(); //! let kp = ntru::generate_key_pair(&DEFAULT_PARAMS_256_BITS, &rand_ctx).unwrap(); //! ``` //! //! This creates a key pair that can be uses to encrypt and decrypt messages: //! //! ``` //! # use ntru::rand::RNG_DEFAULT; //! use ntru::encparams::DEFAULT_PARAMS_256_BITS; //! # //! # let rand_ctx = ntru::rand::init(&RNG_DEFAULT).unwrap(); //! # let kp = ntru::generate_key_pair(&DEFAULT_PARAMS_256_BITS, &rand_ctx).unwrap(); //! //! let msg = b"Hello from Rust!"; //! let encrypted = ntru::encrypt(msg, kp.get_public(), &DEFAULT_PARAMS_256_BITS, //! &rand_ctx).unwrap(); //! let decrypted = ntru::decrypt(&encrypted, &kp, &DEFAULT_PARAMS_256_BITS).unwrap(); //! //! assert_eq!(&msg[..], &decrypted[..]); //! ``` #![forbid(missing_docs, warnings)] #![deny(deprecated, improper_ctypes, non_shorthand_field_patterns, overflowing_literals, plugin_as_library, private_no_mangle_fns, private_no_mangle_statics, stable_features, unconditional_recursion, unknown_lints, unused, unused_allocation, unused_attributes, unused_comparisons, unused_features, unused_parens, while_true)] #![warn(trivial_casts, trivial_numeric_casts, unused, unused_extern_crates, unused_import_braces, unused_qualifications, unused_results, variant_size_differences)] extern crate libc; pub mod types; pub mod rand; pub mod encparams; mod ffi; use types::{KeyPair, PrivateKey, PublicKey, Error}; use encparams::EncParams; use rand::RandContext; /// Key generation /// /// Generates a NTRU encryption key pair. If a deterministic RNG is used, the key pair will be /// deterministic for a given random seed; otherwise, the key pair will be completely random. pub fn generate_key_pair(params: &EncParams, rand_context: &RandContext) -> Result<KeyPair, Error> { let mut kp: KeyPair = Default::default(); let result = unsafe { ffi::ntru_gen_key_pair(params, &mut kp, rand_context) }; if result == 0 { Ok(kp) } else { Err(Error::from(result)) } } /// Key generation with multiple public keys /// /// Generates `num_pub` Ntru encryption key pairs. They all share a private key but their public /// keys differ. The private key decrypts messages encrypted for any of the public keys. Note that /// when decrypting, the public key of the key pair passed into `ntru_decrypt()` must match the /// public key used for encrypting the message. If a deterministic RNG is used, the key pair will /// be deterministic for a given random seed; otherwise, the key pair will be completely random. pub fn generate_multiple_key_pairs(params: &EncParams, rand_context: &RandContext, num_pub: usize) -> Result<(PrivateKey, Box<[PublicKey]>), Error> { let mut private: PrivateKey = Default::default(); let mut public: Vec<PublicKey> = Vec::with_capacity(num_pub); for _ in 0..num_pub { public.push(Default::default()); } let result = unsafe { ffi::ntru_gen_key_pair_multi(params, &mut private, &mut public[0], rand_context, num_pub as u32) }; if result == 0 { Ok((private, public.into_boxed_slice())) } else { Err(Error::from(result)) } } /// New public key /// /// Generates a new public key for an existing private key. The new public key can be used /// interchangeably with the existing public key(s). Generating n keys via /// `ntru::generate_multiple_key_pairs()` is more efficient than generating one and then calling /// `ntru_gen_pub()` n-1 times, so if the number of public keys needed is known beforehand and if /// speed matters, `ntru_gen_key_pair_multi()` should be used. Note that when decrypting, the public /// key of the key pair passed into `ntru_decrypt()` must match the public key used for encrypting /// the message. If a deterministic RNG is used, the key will be deterministic for a given random /// seed; otherwise, the key will be completely random. pub fn generate_public(params: &EncParams, private: &PrivateKey, rand_context: &RandContext) -> Result<PublicKey, Error> { let mut public: PublicKey = Default::default(); let result = unsafe { ffi::ntru_gen_pub(params, private, &mut public, rand_context) }; if result == 0 { Ok(public) } else { Err(Error::from(result)) } } /// Encrypts a message /// /// If a deterministic RNG is used, the encrypted message will also be deterministic for a given /// combination of plain text, key, and random seed. See P1363.1 section 9.2.2. /// The parameters needed are the following: /// * `msg`: The message to encrypt as an ```u8``` slice. /// * `public`: The public key to encrypt the message with. /// * `params`: The NTRU encryption parameters to use. /// * `and_ctx`: An initialized random number generator. pub fn encrypt(msg: &[u8], public: &PublicKey, params: &EncParams, rand_ctx: &RandContext) -> Result<Box<[u8]>, Error> { let mut enc = vec![0u8; params.enc_len() as usize]; let result = unsafe { ffi::ntru_encrypt(if msg.len() > 0 { &msg[0] } else { std::ptr::null() }, msg.len() as u16, public, params, rand_ctx, &mut enc[0]) }; if result == 0 { Ok(enc.into_boxed_slice()) } else { Err(Error::from(result)) } } /// Decrypts a message. /// /// See P1363.1 section 9.2.3. The parameters needed are the following: /// * enc: The message to decrypt as an ```u8``` slice. /// * kp: A key pair that contains the public key the message was encrypted with, and the /// corresponding private key. /// * params: Parameters the message was encrypted with pub fn decrypt(enc: &[u8], kp: &KeyPair, params: &EncParams) -> Result<Box<[u8]>, Error> { let mut dec = vec![0u8; params.max_msg_len() as usize]; let mut dec_len = 0u16; let result = unsafe { ffi::ntru_decrypt(&enc[0], kp, params, &mut dec[0], &mut dec_len) }; if result == 0 { let mut final_dec = Vec::with_capacity(dec_len as usize); final_dec.extend(dec.into_iter().take(dec_len as usize)); Ok(final_dec.into_boxed_slice()) } else { Err(Error::from(result)) } }