#![allow(non_snake_case)]
use super::utils;
use super::Argon2Parameters;
use super::DataType;
use super::Error;
use super::ciphertext::{encrypt, encrypt_asymmetric, Ciphertext, CiphertextVersion};
use super::key::{
derive_keypair, generate_keypair, mix_key_exchange, KeyVersion, PrivateKey, PublicKey,
};
use super::password_hash::{hash_password, PasswordHash, PasswordHashVersion};
use super::secret_sharing::{generate_shared_key, join_shares, SecretSharingVersion, Share};
use super::{
signature,
signature::{Signature, SignatureVersion},
};
use super::{
signing_key,
signing_key::{SigningKeyPair, SigningKeyVersion, SigningPublicKey},
};
use super::Result;
use std::convert::TryFrom as _;
use std::slice;
use zeroize::Zeroize as _;
use base64::{decode_config_slice, encode_config_slice, STANDARD};
const VERSION: &str = env!("CARGO_PKG_VERSION");
#[no_mangle]
pub unsafe extern "C" fn Encrypt(
data: *const u8,
data_length: usize,
key: *const u8,
key_length: usize,
result: *mut u8,
result_length: usize,
version: u16,
) -> i64 {
if data.is_null() || key.is_null() || result.is_null() {
return Error::NullPointer.error_code();
};
if result_length != EncryptSize(data_length, version) as usize {
return Error::InvalidOutputLength.error_code();
}
let data = slice::from_raw_parts(data, data_length);
let key = slice::from_raw_parts(key, key_length);
let result = slice::from_raw_parts_mut(result, result_length);
let version = match CiphertextVersion::try_from(version) {
Ok(v) => v,
Err(_) => return Error::UnknownVersion.error_code(),
};
match encrypt(data, key, version) {
Ok(res) => {
let mut res: Vec<u8> = res.into();
let length = res.len();
result[0..length].copy_from_slice(&res);
res.zeroize();
length as i64
}
Err(e) => e.error_code(),
}
}
#[no_mangle]
pub unsafe extern "C" fn EncryptAsymmetric(
data: *const u8,
data_length: usize,
public_key: *const u8,
public_key_length: usize,
result: *mut u8,
result_length: usize,
version: u16,
) -> i64 {
if data.is_null() || public_key.is_null() || result.is_null() {
return Error::NullPointer.error_code();
};
if result_length != EncryptAsymmetricSize(data_length, version) as usize {
return Error::InvalidOutputLength.error_code();
}
let data = slice::from_raw_parts(data, data_length);
let public_key = PublicKey::try_from(slice::from_raw_parts(public_key, public_key_length));
match public_key {
Ok(public_key) => {
let result = slice::from_raw_parts_mut(result, result_length);
let version = match CiphertextVersion::try_from(version) {
Ok(v) => v,
Err(_) => return Error::UnknownVersion.error_code(),
};
match encrypt_asymmetric(data, &public_key, version) {
Ok(res) => {
let mut res: Vec<u8> = res.into();
let length = res.len();
result[0..length].copy_from_slice(&res);
res.zeroize();
length as i64
}
Err(e) => e.error_code(),
}
}
Err(e) => e.error_code(),
}
}
#[no_mangle]
pub extern "C" fn EncryptSize(data_length: usize, version: u16) -> i64 {
match version {
1 => {
(8 + 16 + (data_length / 16 + 1) * 16 + 32) as i64 }
0 | 2 => {
(8 + 24 + data_length + 16) as i64 }
_ => Error::UnknownVersion.error_code(),
}
}
#[no_mangle]
pub extern "C" fn EncryptAsymmetricSize(data_length: usize, version: u16) -> i64 {
match version {
0 | 2 => {
(8 + 32 + 24 + data_length + 16) as i64 }
_ => Error::UnknownVersion.error_code(),
}
}
#[no_mangle]
pub unsafe extern "C" fn Decrypt(
data: *const u8,
data_length: usize,
key: *const u8,
key_length: usize,
result: *mut u8,
result_length: usize,
) -> i64 {
if data.is_null() || key.is_null() || result.is_null() {
return Error::NullPointer.error_code();
};
let data = slice::from_raw_parts(data, data_length);
let key = slice::from_raw_parts(key, key_length);
let result = slice::from_raw_parts_mut(result, result_length);
match Ciphertext::try_from(data) {
Ok(res) => match res.decrypt(key) {
Ok(mut res) => {
if result.len() >= res.len() {
let length = res.len();
result[0..length].copy_from_slice(&res);
res.zeroize();
length as i64
} else {
res.zeroize();
Error::InvalidOutputLength.error_code()
}
}
Err(e) => e.error_code(),
},
Err(e) => e.error_code(),
}
}
#[no_mangle]
pub unsafe extern "C" fn DecryptAsymmetric(
data: *const u8,
data_length: usize,
private_key: *const u8,
private_key_length: usize,
result: *mut u8,
result_length: usize,
) -> i64 {
if data.is_null() || private_key.is_null() || result.is_null() {
return Error::NullPointer.error_code();
};
let data = slice::from_raw_parts(data, data_length);
let private_key = PrivateKey::try_from(slice::from_raw_parts(private_key, private_key_length));
match private_key {
Ok(private_key) => {
let result = slice::from_raw_parts_mut(result, result_length);
match Ciphertext::try_from(data) {
Ok(res) => match res.decrypt_asymmetric(&private_key) {
Ok(mut res) => {
if result.len() >= res.len() {
let length = res.len();
result[0..length].copy_from_slice(&res);
res.zeroize();
length as i64
} else {
res.zeroize();
Error::InvalidOutputLength.error_code()
}
}
Err(e) => e.error_code(),
},
Err(e) => e.error_code(),
}
}
Err(e) => e.error_code(),
}
}
#[no_mangle]
pub unsafe extern "C" fn Sign(
data: *const u8,
data_length: usize,
keypair: *const u8,
keypair_length: usize,
result: *mut u8,
result_length: usize,
version: u16,
) -> i64 {
if data.is_null() || keypair.is_null() || result.is_null() {
return Error::NullPointer.error_code();
};
if result_length != SignSize(version) as usize {
return Error::InvalidOutputLength.error_code();
};
let data = slice::from_raw_parts(data, data_length);
let keypair = slice::from_raw_parts(keypair, keypair_length);
let result = slice::from_raw_parts_mut(result, result_length);
match SigningKeyPair::try_from(keypair) {
Ok(keypair) => {
let version = match SignatureVersion::try_from(version) {
Ok(v) => v,
Err(_) => return Error::UnknownVersion.error_code(),
};
let signature: Vec<u8> = signature::sign(data, &keypair, version).into();
result[0..signature.len()].copy_from_slice(&signature);
0
}
Err(e) => e.error_code(),
}
}
#[no_mangle]
pub unsafe extern "C" fn VerifySignature(
data: *const u8,
data_length: usize,
public_key: *const u8,
public_key_length: usize,
signature: *const u8,
signature_length: usize,
) -> i64 {
if data.is_null() || public_key.is_null() || signature.is_null() {
return Error::NullPointer.error_code();
};
let data = slice::from_raw_parts(data, data_length);
let public_key = slice::from_raw_parts(public_key, public_key_length);
let signature = slice::from_raw_parts(signature, signature_length);
match SigningPublicKey::try_from(public_key) {
Ok(public_key) => match Signature::try_from(signature) {
Ok(signature) => {
if signature.verify(data, &public_key) {
1
} else {
0
}
}
Err(e) => e.error_code(),
},
Err(e) => e.error_code(),
}
}
#[no_mangle]
pub extern "C" fn SignSize(_version: u16) -> i64 {
8 + 64 }
#[no_mangle]
pub unsafe extern "C" fn HashPassword(
password: *const u8,
password_length: usize,
iterations: u32,
result: *mut u8,
result_length: usize,
) -> i64 {
if password.is_null() || result.is_null() {
return Error::NullPointer.error_code();
};
if result_length != HashPasswordLength() as usize {
return Error::InvalidOutputLength.error_code();
};
let password = slice::from_raw_parts(password, password_length);
let result = slice::from_raw_parts_mut(result, result_length);
let mut res: Vec<u8> = hash_password(password, iterations, PasswordHashVersion::Latest).into();
let length = res.len();
result[0..length].copy_from_slice(&res);
res.zeroize();
length as i64
}
#[no_mangle]
pub extern "C" fn HashPasswordLength() -> i64 {
8 + 4 + 32 + 32 }
#[no_mangle]
pub unsafe extern "C" fn VerifyPassword(
password: *const u8,
password_length: usize,
hash: *const u8,
hash_length: usize,
) -> i64 {
if password.is_null() || hash.is_null() {
return Error::NullPointer.error_code();
};
let password = slice::from_raw_parts(password, password_length);
let hash = slice::from_raw_parts(hash, hash_length);
match PasswordHash::try_from(hash) {
Ok(res) => {
if res.verify_password(password) {
1
} else {
0
}
}
Err(e) => e.error_code(),
}
}
#[no_mangle]
pub unsafe extern "C" fn GenerateKeyPair(
private: *mut u8,
private_length: usize,
public: *mut u8,
public_length: usize,
) -> i64 {
if private.is_null() || public.is_null() {
return Error::NullPointer.error_code();
};
if private_length != GenerateKeyPairSize() as usize
|| public_length != GenerateKeyPairSize() as usize
{
return Error::InvalidOutputLength.error_code();
}
let private = slice::from_raw_parts_mut(private, private_length);
let public = slice::from_raw_parts_mut(public, public_length);
let keypair = generate_keypair(KeyVersion::Latest);
let mut priv_res: Vec<u8> = keypair.private_key.into();
let mut pub_res: Vec<u8> = keypair.public_key.into();
public[0..pub_res.len()].copy_from_slice(&pub_res);
private[0..priv_res.len()].copy_from_slice(&priv_res);
priv_res.zeroize();
pub_res.zeroize();
0
}
#[no_mangle]
pub unsafe extern "C" fn GenerateSigningKeyPair(
keypair: *mut u8,
keypair_length: usize,
version: u16,
) -> i64 {
if keypair.is_null() {
return Error::NullPointer.error_code();
};
if keypair_length != GenerateSigningKeyPairSize(version) as usize {
return Error::InvalidOutputLength.error_code();
}
let keypair = slice::from_raw_parts_mut(keypair, keypair_length);
let version = match SigningKeyVersion::try_from(version) {
Ok(v) => v,
Err(_) => return Error::UnknownVersion.error_code(),
};
let generated_keypair = signing_key::generate_signing_keypair(version);
let mut keypair_bytes: Vec<u8> = generated_keypair.into();
keypair[0..keypair_bytes.len()].copy_from_slice(&keypair_bytes);
keypair_bytes.zeroize();
0
}
#[no_mangle]
pub unsafe extern "C" fn GetSigningPublicKey(
keypair: *const u8,
keypair_length: usize,
public: *mut u8,
public_length: usize,
) -> i64 {
if keypair.is_null() || public.is_null() {
return Error::NullPointer.error_code();
};
if public_length != GetSigningPublicKeySize(keypair, keypair_length) as usize {
return Error::InvalidOutputLength.error_code();
};
let keypair = slice::from_raw_parts(keypair, keypair_length);
let public = slice::from_raw_parts_mut(public, public_length);
let keypair = SigningKeyPair::try_from(keypair);
match keypair {
Ok(keypair) => {
let public_key: Vec<u8> = keypair.get_public_key().into();
public[..public_key.len()].copy_from_slice(&public_key);
0
}
Err(e) => e.error_code(),
}
}
#[no_mangle]
pub extern "C" fn GenerateKeyPairSize() -> i64 {
8 + 32 }
#[no_mangle]
pub extern "C" fn GenerateSigningKeyPairSize(_version: u16) -> i64 {
8 + 64 }
#[no_mangle]
pub extern "C" fn GetSigningPublicKeySize(_keypair: *const u8, _keypair_length: usize) -> i64 {
8 + 32 }
#[no_mangle]
pub extern "C" fn DeriveKeyPairSize() -> i64 {
GenerateKeyPairSize()
}
#[no_mangle]
pub unsafe extern "C" fn MixKeyExchange(
private: *const u8,
private_size: usize,
public: *const u8,
public_size: usize,
shared: *mut u8,
shared_size: usize,
) -> i64 {
if private.is_null() || public.is_null() || shared.is_null() {
return Error::NullPointer.error_code();
};
if shared_size != MixKeyExchangeSize() as usize {
return Error::InvalidOutputLength.error_code();
}
let public = slice::from_raw_parts(public, public_size);
let private = slice::from_raw_parts(private, private_size);
let shared = slice::from_raw_parts_mut(shared, shared_size);
match (PrivateKey::try_from(private), PublicKey::try_from(public)) {
(Ok(private), Ok(public)) => match mix_key_exchange(&private, &public) {
Ok(mut res) => {
shared[0..res.len()].copy_from_slice(&res);
res.zeroize();
0
}
Err(e) => e.error_code(),
},
(Ok(_), Err(e)) => e.error_code(),
(Err(e), Ok(_)) => e.error_code(),
(Err(e), Err(_)) => e.error_code(),
}
}
#[no_mangle]
pub extern "C" fn MixKeyExchangeSize() -> i64 {
32
}
#[no_mangle]
pub unsafe extern "C" fn GenerateSharedKey(
n_shares: u8,
threshold: u8,
length: usize,
shares: *const *mut u8,
) -> i64 {
if shares.is_null() {
return Error::NullPointer.error_code();
};
match generate_shared_key(n_shares, threshold, length, SecretSharingVersion::Latest) {
Ok(s) => {
let shares = slice::from_raw_parts(shares, n_shares as usize);
for (s, res_s) in s.into_iter().zip(shares) {
if res_s.is_null() {
return Error::NullPointer.error_code();
};
let s: Vec<u8> = s.into();
let res_s =
slice::from_raw_parts_mut(*res_s, GenerateSharedKeySize(length) as usize);
res_s.copy_from_slice(&s);
}
0
}
Err(e) => e.error_code(),
}
}
#[no_mangle]
pub extern "C" fn GenerateSharedKeySize(secret_length: usize) -> i64 {
(secret_length + 10) as i64
}
#[no_mangle]
pub unsafe extern "C" fn JoinShares(
n_shares: usize,
share_length: usize,
shares: *const *const u8,
secret: *mut u8,
secret_length: usize,
) -> i64 {
if shares.is_null() || secret.is_null() {
return Error::NullPointer.error_code();
};
if secret_length != JoinSharesSize(share_length) as usize {
return Error::InvalidOutputLength.error_code();
}
let shares: Result<Vec<Share>> = slice::from_raw_parts(shares, n_shares)
.iter()
.map(|s| Share::try_from(slice::from_raw_parts(*s, share_length)))
.collect();
match shares {
Ok(shares) => match join_shares(&shares) {
Ok(s) => {
let secret = slice::from_raw_parts_mut(secret, secret_length);
secret.copy_from_slice(&s);
0
}
Err(e) => e.error_code(),
},
Err(e) => e.error_code(),
}
}
#[no_mangle]
pub extern "C" fn JoinSharesSize(share_length: usize) -> i64 {
(share_length - 10) as i64
}
#[no_mangle]
pub unsafe extern "C" fn GenerateKey(key: *mut u8, key_length: usize) -> i64 {
if key.is_null() {
return Error::NullPointer.error_code();
};
let key = slice::from_raw_parts_mut(key, key_length);
let mut k = utils::generate_key(key_length);
key.copy_from_slice(&k);
k.zeroize();
0
}
#[no_mangle]
pub unsafe extern "C" fn DeriveKeyArgon2(
key: *const u8,
key_length: usize,
argon2_parameters: *const u8,
argon2_parameters_length: usize,
result: *mut u8,
result_length: usize,
) -> i64 {
if key.is_null() || result.is_null() || argon2_parameters.is_null() {
return Error::NullPointer.error_code();
};
let key = slice::from_raw_parts(key, key_length);
let argon2_parameters_raw = slice::from_raw_parts(argon2_parameters, argon2_parameters_length);
let argon2_parameters = match Argon2Parameters::try_from(argon2_parameters_raw) {
Ok(x) => x,
Err(e) => return e.error_code(),
};
let mut native_result = match utils::derive_key_argon2(&key, &argon2_parameters) {
Ok(x) => x,
Err(e) => return e.error_code(),
};
let result = slice::from_raw_parts_mut(result, result_length);
result.copy_from_slice(&native_result);
native_result.zeroize();
0
}
#[no_mangle]
pub unsafe extern "C" fn DeriveKeyPbkdf2(
key: *const u8,
key_length: usize,
salt: *const u8,
salt_length: usize,
niterations: u32,
result: *mut u8,
result_length: usize,
) -> i64 {
if key.is_null() || result.is_null() {
return Error::NullPointer.error_code();
};
let salt = if salt.is_null() || salt_length == 0 {
b""
} else {
slice::from_raw_parts(salt, salt_length)
};
let key = slice::from_raw_parts(key, key_length);
let result = slice::from_raw_parts_mut(result, result_length);
let mut native_result = utils::derive_key_pbkdf2(&key, &salt, niterations, result_length);
result.copy_from_slice(&native_result);
native_result.zeroize();
0
}
#[no_mangle]
pub unsafe extern "C" fn ValidateHeader(
data: *const u8,
data_length: usize,
data_type: u16,
) -> i64 {
if data.is_null() {
return Error::NullPointer.error_code();
};
let data = slice::from_raw_parts(data, data_length);
match DataType::try_from(data_type) {
Ok(t) => {
if utils::validate_header(data, t) {
1
} else {
0
}
}
Err(_) => Error::UnknownType.error_code(),
}
}
#[no_mangle]
pub unsafe extern "C" fn ScryptSimple(
password: *const u8,
password_length: usize,
salt: *const u8,
salt_length: usize,
log_n: u8,
r: u32,
p: u32,
output: *mut u8,
output_length: usize,
) -> i64 {
if password.is_null() && salt.is_null() && output.is_null() {
return Error::NullPointer.error_code();
};
let password = slice::from_raw_parts(password, password_length);
let salt = slice::from_raw_parts(salt, salt_length);
let hash = utils::scrypt_simple(password, salt, log_n, r, p);
let output = slice::from_raw_parts_mut(output, output_length);
output[..hash.len()].copy_from_slice(hash.as_bytes());
hash.len() as i64
}
#[no_mangle]
pub unsafe extern "C" fn ScryptSimpleSize() -> i64 {
256
}
#[no_mangle]
pub unsafe extern "C" fn GetDefaultArgon2Parameters(
argon2_parameters: *mut u8,
argon2_parameters_length: usize,
) -> i64 {
let argon2_parameters = slice::from_raw_parts_mut(argon2_parameters, argon2_parameters_length);
let argon2_parameters_raw: Vec<u8> = Argon2Parameters::default().into();
argon2_parameters.copy_from_slice(&argon2_parameters_raw);
0
}
#[no_mangle]
pub extern "C" fn GetDefaultArgon2ParametersSize() -> i64 {
46
}
#[no_mangle]
pub unsafe extern "C" fn DeriveKeyPair(
password: *const u8,
password_length: usize,
parameters: *const u8,
parameters_length: usize,
private_key: *mut u8,
private_key_length: usize,
public_key: *mut u8,
public_key_length: usize,
) -> i64 {
if password.is_null() || parameters.is_null() || private_key.is_null() || public_key.is_null() {
return Error::NullPointer.error_code();
};
if private_key_length != DeriveKeyPairSize() as usize
|| public_key_length != DeriveKeyPairSize() as usize
{
return Error::InvalidOutputLength.error_code();
}
let password = slice::from_raw_parts(password, password_length);
let private_key = slice::from_raw_parts_mut(private_key, private_key_length);
let public_key = slice::from_raw_parts_mut(public_key, public_key_length);
let parameters =
Argon2Parameters::try_from(slice::from_raw_parts(parameters, parameters_length));
let parameters = match parameters {
Ok(x) => x,
Err(e) => return e.error_code(),
};
match derive_keypair(password, ¶meters, KeyVersion::Latest) {
Ok(keypair) => {
let private: Vec<u8> = keypair.private_key.into();
let public: Vec<u8> = keypair.public_key.into();
private_key.copy_from_slice(&private);
public_key.copy_from_slice(&public);
0
}
Err(e) => e.error_code(),
}
}
#[no_mangle]
pub extern "C" fn KeySize() -> u32 {
256
}
#[no_mangle]
pub unsafe extern "C" fn Decode(
input: *const u8,
input_length: usize,
output: *mut u8,
output_length: usize,
) -> i64 {
if input.is_null() || output.is_null() {
return Error::NullPointer.error_code();
};
let input = std::str::from_utf8_unchecked(slice::from_raw_parts(input, input_length));
let mut output = slice::from_raw_parts_mut(output, output_length);
match decode_config_slice(&input, STANDARD, &mut output) {
Ok(res) => res as i64,
Err(_e) => -1,
}
}
#[no_mangle]
pub unsafe extern "C" fn Encode(
input: *const u8,
input_length: usize,
output: *mut u8,
output_length: usize,
) -> i64 {
if input.is_null() || output.is_null() {
return Error::NullPointer.error_code();
};
let input = slice::from_raw_parts(input, input_length);
let mut output = slice::from_raw_parts_mut(output, output_length);
encode_config_slice(&input, STANDARD, &mut output) as i64
}
#[no_mangle]
pub unsafe extern "C" fn DecodeUrl(
input: *const u8,
input_length: usize,
output: *mut u8,
output_length: usize,
) -> i64 {
if input.is_null() || output.is_null() {
return Error::NullPointer.error_code();
};
let input = std::str::from_utf8_unchecked(slice::from_raw_parts(input, input_length));
let mut output = slice::from_raw_parts_mut(output, output_length);
let config = base64::Config::new(base64::CharacterSet::UrlSafe, false);
match decode_config_slice(&input, config, &mut output) {
Ok(res) => res as i64,
Err(_e) => -1,
}
}
#[no_mangle]
pub unsafe extern "C" fn EncodeUrl(
input: *const u8,
input_length: usize,
output: *mut u8,
output_length: usize,
) -> i64 {
if input.is_null() || output.is_null() {
return Error::NullPointer.error_code();
};
let input = slice::from_raw_parts(input, input_length);
let mut output = slice::from_raw_parts_mut(output, output_length);
let config = base64::Config::new(base64::CharacterSet::UrlSafe, false);
encode_config_slice(&input, config, &mut output) as i64
}
#[no_mangle]
pub extern "C" fn VersionSize() -> i64 {
VERSION.len() as i64
}
#[no_mangle]
pub unsafe extern "C" fn Version(output: *mut u8, output_length: usize) -> i64 {
if output.is_null() {
return Error::NullPointer.error_code();
};
let output = slice::from_raw_parts_mut(output, output_length);
output.copy_from_slice(&VERSION.as_bytes());
output.len() as i64
}
#[test]
fn test_encrypt_length() {
let key = b"supersecret";
let length_zero = b"";
let length_one_block = b"hello";
let one_full_block = b"0123456789abcdef";
let multiple_blocks = b"0123456789abcdefghijkl";
let length_zero_enc: Vec<u8> = encrypt(length_zero, key, CiphertextVersion::Latest)
.unwrap()
.into();
let length_one_block_enc: Vec<u8> = encrypt(length_one_block, key, CiphertextVersion::Latest)
.unwrap()
.into();
let one_full_block_enc: Vec<u8> = encrypt(one_full_block, key, CiphertextVersion::Latest)
.unwrap()
.into();
let multiple_blocks_enc: Vec<u8> = encrypt(multiple_blocks, key, CiphertextVersion::Latest)
.unwrap()
.into();
assert_eq!(
length_zero_enc.len() as i64,
EncryptSize(length_zero.len(), 0)
);
assert_eq!(
length_one_block_enc.len() as i64,
EncryptSize(length_one_block.len(), 0)
);
assert_eq!(
one_full_block_enc.len() as i64,
EncryptSize(one_full_block.len(), 0)
);
assert_eq!(
multiple_blocks_enc.len() as i64,
EncryptSize(multiple_blocks.len(), 0)
);
}
#[test]
fn test_hash_password_length() {
let small_password = b"pass";
let long_password = b"this is a very long and complicated password that is, I hope,\
longer than the length of the actual hash. It also contains we1rd pa$$w0rd///s.\\";
let small_password_hash: Vec<u8> =
hash_password(small_password, 100, PasswordHashVersion::Latest).into();
let long_password_hash: Vec<u8> =
hash_password(long_password, 2642, PasswordHashVersion::Latest).into();
assert_eq!(HashPasswordLength() as usize, small_password_hash.len());
assert_eq!(HashPasswordLength() as usize, long_password_hash.len());
}
#[test]
fn test_key_exchange_length() {
let bob_keypair = generate_keypair(KeyVersion::Latest);
let alice_keypair = generate_keypair(KeyVersion::Latest);
let private_bob: Vec<u8> = bob_keypair.private_key.into();
let public_bob: Vec<u8> = bob_keypair.public_key.into();
assert_eq!(GenerateKeyPairSize() as usize, private_bob.len());
assert_eq!(GenerateKeyPairSize() as usize, public_bob.len());
let private_bob = PrivateKey::try_from(private_bob.as_slice()).unwrap();
let public_bob = PublicKey::try_from(public_bob.as_slice()).unwrap();
let shared_bob = mix_key_exchange(&private_bob, &alice_keypair.public_key).unwrap();
let shared_alice = mix_key_exchange(&alice_keypair.private_key, &public_bob).unwrap();
assert_eq!(MixKeyExchangeSize() as usize, shared_bob.len());
assert_eq!(MixKeyExchangeSize() as usize, shared_alice.len());
}
#[test]
fn test_get_default_argon2parameters_size() {
assert_eq!(GetDefaultArgon2ParametersSize(), 46);
}
#[test]
fn test_get_default_argon2parameters() {
let mut argon2_parameters_vec: Vec<u8> = vec![0u8; GetDefaultArgon2ParametersSize() as usize];
let argon2_parameters_raw = argon2_parameters_vec.as_mut_ptr();
unsafe {
let result = GetDefaultArgon2Parameters(
argon2_parameters_raw,
GetDefaultArgon2ParametersSize() as usize,
);
assert_eq!(result, 0);
}
unsafe {
let argon2_parameters = slice::from_raw_parts(
argon2_parameters_raw,
GetDefaultArgon2ParametersSize() as usize,
);
let _params = Argon2Parameters::try_from(argon2_parameters).unwrap();
let defaults: Vec<u8> = Argon2Parameters::default().into();
let received: Vec<u8> = argon2_parameters.to_vec();
assert_eq!(
defaults[..defaults.len() - 16],
received[..received.len() - 16]
);
}
}
#[test]
fn test_derive_keypair() {
let small_password = b"pass".to_vec();
let long_password = b"this is a very long and complicated password that is, I hope,\
longer than the length of the actual hash. It also contains we1rd pa$$w0rd///s.\\"
.to_vec();
let parameters: Vec<u8> = Argon2Parameters::default().into();
let mut private_key_vec = vec![0u8; DeriveKeyPairSize() as usize];
let private_key = private_key_vec.as_mut_ptr();
let mut public_key_vec = vec![0u8; DeriveKeyPairSize() as usize];
let public_key = public_key_vec.as_mut_ptr();
unsafe {
let result_small = DeriveKeyPair(
small_password.as_ptr(),
small_password.len(),
parameters.as_ptr(),
parameters.len(),
private_key,
DeriveKeyPairSize() as usize,
public_key,
DeriveKeyPairSize() as usize,
);
assert_eq!(0i64, result_small);
let result_long = DeriveKeyPair(
long_password.as_ptr(),
long_password.len(),
parameters.as_ptr(),
parameters.len(),
private_key,
DeriveKeyPairSize() as usize,
public_key,
DeriveKeyPairSize() as usize,
);
assert_eq!(0i64, result_long);
}
let data = b"SomeData".to_vec();
let encrypt_size = EncryptAsymmetricSize(data.len(), 2);
let mut result_encrypt_vec = vec![0u8; encrypt_size as usize];
let result_encrypt = result_encrypt_vec.as_mut_ptr();
unsafe {
let result_code_encrypt = EncryptAsymmetric(
data.as_ptr(),
data.len(),
public_key,
DeriveKeyPairSize() as usize,
result_encrypt,
encrypt_size as usize,
2,
);
assert_eq!(encrypt_size, result_code_encrypt)
}
let mut result_decrypt_vec = vec![0u8; encrypt_size as usize];
let result_decrypt = result_decrypt_vec.as_mut_ptr();
unsafe {
let result_code_decrypt = DecryptAsymmetric(
result_encrypt,
encrypt_size as usize,
private_key,
DeriveKeyPairSize() as usize,
result_decrypt,
encrypt_size as usize,
);
assert!(result_code_decrypt >= 0);
let decrypt_data = slice::from_raw_parts_mut(result_decrypt, result_code_decrypt as usize);
assert_eq!(data, decrypt_data);
}
}