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
//! NTRUEncrypt implementation for Rust
//!
//! This library implements the NtruEncrypt library in Rust. It is an interface to libntru, even
//! though many of the methds 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 NTRUEncrypt implementation. In any case, it is much faster than usual encryption /
//! decryption mecanisms, and quantum-proof. More on NTRUEncrypt
//! [here](https://en.wikipedia.org/wiki/NTRUEncrypt).
//!
//! To use it you only need to include the following in your crate:
//! ```
//! extern crate ntru;
//!```
//!
//! NTRUEncrypt uses its own keys, that must be generated with the included random key generator,
//! and must not be used for other applications such as NTRUSign or NTRUNMLS. Here is an example of
//! use:
//!
//! ```
//! use ntru::rand::NTRU_RNG_DEFAULT;
//! use ntru::encparams::NTRU_DEFAULT_PARAMS_256_BITS;
//!
//! let rand_ctx = ntru::rand::init(&NTRU_RNG_DEFAULT).ok().unwrap();
//! let kp = ntru::generate_key_pair(&NTRU_DEFAULT_PARAMS_256_BITS, &rand_ctx).ok().unwrap();
//! ```
//!
//! This creates a key pair that can be uses to encrypt and decrypt messages:
//!
//! ```
//! use ntru::rand::NTRU_RNG_DEFAULT;
//! use ntru::encparams::NTRU_DEFAULT_PARAMS_256_BITS;
//! #
//! # let rand_ctx = ntru::rand::init(&NTRU_RNG_DEFAULT).ok().unwrap();
//! # let kp = ntru::generate_key_pair(&NTRU_DEFAULT_PARAMS_256_BITS, &rand_ctx).ok().unwrap();
//!
//! let msg = b"Hello from Rust!";
//! let encrypted = ntru::encrypt(msg, kp.get_public(), &NTRU_DEFAULT_PARAMS_256_BITS,
//!                               &rand_ctx).ok().unwrap();
//! let decrypted = ntru::decrypt(&encrypted, &kp, &NTRU_DEFAULT_PARAMS_256_BITS).ok().unwrap();
//!
//! assert_eq!(&msg[..], &decrypted[..]);
//! ```
extern crate libc;

pub mod types;
pub mod rand;
pub mod encparams;
mod ffi;

use types::{NtruEncKeyPair, NtruEncPubKey, NtruError};
use encparams::NtruEncParams;
use rand::NtruRandContext;

/// Key generation
///
/// Generates a NtruEncrypt 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: &NtruEncParams, rand_context: &NtruRandContext)
                        -> Result<NtruEncKeyPair, NtruError> {
    let mut kp: NtruEncKeyPair = Default::default();
    let result = unsafe {ffi::ntru_gen_key_pair(params, &mut kp, rand_context)};
    if result == 0 {
        Ok(kp)
    } else {
        Err(NtruError::from_uint8_t(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 NtruEncrypt parameters to use.
/// * and_ctx: An initialized random number generator.
pub fn encrypt(msg: &[u8], public: &NtruEncPubKey, params: &NtruEncParams,
                rand_ctx: &NtruRandContext) -> Result<Box<[u8]>, NtruError> {
    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(NtruError::from_uint8_t(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: &NtruEncKeyPair, params: &NtruEncParams)
                -> Result<Box<[u8]>, NtruError> {
    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);
        for i in 0..(dec_len as usize) {
            final_dec.push(dec[i]);
        }
        Ok(final_dec.into_boxed_slice())
    } else {
        Err(NtruError::from_uint8_t(result))
    }
}