adding rust interface

pull/1/head
Avril 4 years ago
parent f143d1cd2c
commit e113c90c53
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -5,6 +5,7 @@ use std::{
}, },
}; };
/// An algorithm to use for the context.
#[derive(Clone,Debug,PartialEq,Eq,Hash)] #[derive(Clone,Debug,PartialEq,Eq,Hash)]
pub enum Algorithm pub enum Algorithm
{ {
@ -22,6 +23,7 @@ impl Default for Algorithm
} }
} }
/// A kana-hash context containing it's salt and algorithm.
#[derive(Clone,Debug,PartialEq,Eq,Hash)] #[derive(Clone,Debug,PartialEq,Eq,Hash)]
pub struct Context pub struct Context
{ {
@ -31,6 +33,7 @@ pub struct Context
impl Context impl Context
{ {
/// Create a new kana-hash context with an algorithm and a salt
pub fn new(algo: Algorithm, salt: impl Into<salt::Salt>) -> Self pub fn new(algo: Algorithm, salt: impl Into<salt::Salt>) -> Self
{ {
Self { Self {
@ -38,16 +41,20 @@ impl Context
salt: salt.into(), salt: salt.into(),
} }
} }
/// The algorithm used
pub fn get_algorithm(&self) -> &Algorithm pub fn get_algorithm(&self) -> &Algorithm
{ {
&self.algo &self.algo
} }
/// The salt used
pub fn get_salt(&self) -> &salt::Salt pub fn get_salt(&self) -> &salt::Salt
{ {
&self.salt &self.salt
} }
pub fn compute<R: Read>(&self, mut from: R) -> Result<(usize, Box<[u8]>), error::Error>
pub(crate) fn compute<R: Read>(&self, mut from: R) -> Result<(usize, Box<[u8]>), error::Error>
{ {
fn provide<P,R>(input: &mut R, salt: &salt::Salt, output: &mut usize) -> Result<Vec<u8>, error::Error> fn provide<P,R>(input: &mut R, salt: &salt::Salt, output: &mut usize) -> Result<Vec<u8>, error::Error>
where P: provider::ByteProvider, where P: provider::ByteProvider,
@ -69,7 +76,7 @@ impl Context
Ok((output, bytes)) Ok((output, bytes))
} }
pub unsafe fn into_raw(self) -> CContext pub(crate) unsafe fn into_raw(self) -> CContext
{ {
CContext{ CContext{
algo: u8::from(self.algo), algo: u8::from(self.algo),
@ -78,7 +85,7 @@ impl Context
} }
} }
pub unsafe fn clone_from_raw(from: *const CContext) -> Self pub(crate) unsafe fn clone_from_raw(from: *const CContext) -> Self
{ {
let from = &*from; let from = &*from;
Self { Self {
@ -87,7 +94,7 @@ impl Context
} }
} }
pub unsafe fn from_raw(from: *mut CContext) -> Self pub(crate) unsafe fn from_raw(from: *mut CContext) -> Self
{ {
let from = &mut *from; let from = &mut *from;
let output = Self{ let output = Self{
@ -110,16 +117,16 @@ impl Default for Context
} }
} }
pub const ALGO_DEFAULT: u8 = 0; pub(crate) const ALGO_DEFAULT: u8 = 0;
pub const ALGO_CRC32: u8 = 1; pub(crate) const ALGO_CRC32: u8 = 1;
pub const ALGO_CRC64: u8 = 2; pub(crate) const ALGO_CRC64: u8 = 2;
pub const ALGO_SHA256: u8 = 3; pub(crate) const ALGO_SHA256: u8 = 3;
pub const ALGO_SHA256_TRUNCATED: u8 = 4; pub(crate) const ALGO_SHA256_TRUNCATED: u8 = 4;
/// FFI context /// FFI context
#[derive(Debug)] #[derive(Debug)]
#[repr(C)] #[repr(C)]
pub struct CContext pub(crate) struct CContext
{ {
algo: u8, algo: u8,
flags: u64, //nothing yet, might be flags later idk flags: u64, //nothing yet, might be flags later idk

@ -4,13 +4,19 @@ use std::{
error, error,
}; };
/// An error value used by all kana-hash functions.
#[derive(Debug)] #[derive(Debug)]
pub enum Error pub enum Error
{ {
/// There was an IO error reading or writing a buffer.
IO(io::Error), IO(io::Error),
/// There was a text formatting error writing the context.
Format(fmt::Error), Format(fmt::Error),
/// There was a length mismatch.
Length{expected: usize, got:usize,}, Length{expected: usize, got:usize,},
/// The random number generator failed.
RNG(getrandom::Error), RNG(getrandom::Error),
/// There was an unknown error.
Unknown, Unknown,
} }

@ -242,12 +242,14 @@ mod sixteen;
use sixteen::Bit16IterExt; use sixteen::Bit16IterExt;
mod def; mod def;
mod map; mod map;
mod salt; pub mod salt;
mod hash; mod hash;
mod provider; mod provider;
mod mnemonic; mod mnemonic;
mod error; pub mod error;
mod ctx; pub mod ctx;
mod stream;
pub use stream::Digest;
#[macro_use] #[macro_use]
mod ffi; mod ffi;
@ -269,6 +271,7 @@ fn compute<T: Read>(context: &ctx::Context, mut from: T) -> Result<(usize, Strin
Ok((read,output)) Ok((read,output))
} }
/// Generate kana hash from a slice.
pub fn generate<T: AsRef<[u8]>>(context: &ctx::Context, bytes: T) -> Result<String, error::Error> pub fn generate<T: AsRef<[u8]>>(context: &ctx::Context, bytes: T) -> Result<String, error::Error>
{ {
let bytes = bytes.as_ref(); let bytes = bytes.as_ref();
@ -291,6 +294,8 @@ use malloc_array::{
HeapArray, HeapArray,
}; };
// FFI section // FFI section
/// Calculate the length in bytes of a kana hash output. /// Calculate the length in bytes of a kana hash output.
@ -298,8 +303,9 @@ use malloc_array::{
/// # Note /// # Note
/// Does not consume `salt` /// Does not consume `salt`
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn khash_length(context: *const ctx::CContext, bin: *const c_void, sz: size_t, out_len: *mut size_t) -> i32 pub unsafe extern "C" fn khash_length(context: *const c_void, bin: *const c_void, sz: size_t, out_len: *mut size_t) -> i32
{ {
let context = context as *const ctx::CContext;
no_unwind!{ no_unwind!{
try error::Error::Unknown; try error::Error::Unknown;
let context = ctx::Context::clone_from_raw(context); let context = ctx::Context::clone_from_raw(context);
@ -316,8 +322,9 @@ pub unsafe extern "C" fn khash_length(context: *const ctx::CContext, bin: *const
/// # Note /// # Note
/// Consumes `salt` /// Consumes `salt`
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn khash_do(context: *mut ctx::CContext, bin: *const c_void, sz: size_t, out_str: *mut c_char, str_len: size_t) -> i32 pub unsafe extern "C" fn khash_do(context: *mut c_void, bin: *const c_void, sz: size_t, out_str: *mut c_char, str_len: size_t) -> i32
{ {
let context = context as *mut ctx::CContext;
no_unwind!{ no_unwind!{
try error::Error::Unknown; try error::Error::Unknown;
@ -333,8 +340,9 @@ pub unsafe extern "C" fn khash_do(context: *mut ctx::CContext, bin: *const c_voi
/// Free a context /// Free a context
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn khash_free_context(context: *mut ctx::CContext) -> i32 pub unsafe extern "C" fn khash_free_context(context: *mut c_void) -> i32
{ {
let context = context as *mut ctx::CContext;
no_unwind!{ no_unwind!{
drop(ctx::Context::from_raw(context)); drop(ctx::Context::from_raw(context));
GENERIC_SUCCESS GENERIC_SUCCESS
@ -343,8 +351,9 @@ pub unsafe extern "C" fn khash_free_context(context: *mut ctx::CContext) -> i32
/// Create a new context /// Create a new context
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn khash_new_context(algo: u8, salt_type: u8, bin: *const c_void, sz: size_t, nptr: *mut ctx::CContext) -> i32 pub unsafe extern "C" fn khash_new_context(algo: u8, salt_type: u8, bin: *const c_void, sz: size_t, nptr: *mut c_void) -> i32
{ {
let nptr = nptr as *mut ctx::CContext;
no_unwind!{ no_unwind!{
try error::Error::Unknown; try error::Error::Unknown;
let salt = match salt_type { let salt = match salt_type {
@ -374,8 +383,10 @@ pub unsafe extern "C" fn khash_new_context(algo: u8, salt_type: u8, bin: *const
/// Clone a context /// Clone a context
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn khash_clone_context(raw: *const ctx::CContext, out: *mut ctx::CContext) -> i32 pub unsafe extern "C" fn khash_clone_context(raw: *const c_void, out: *mut c_void) -> i32
{ {
let raw = raw as *const ctx::CContext;
let out = out as *mut ctx::CContext;
no_unwind!{ no_unwind!{
*out = ctx::Context::clone_from_raw(raw).into_raw(); *out = ctx::Context::clone_from_raw(raw).into_raw();
GENERIC_SUCCESS GENERIC_SUCCESS
@ -384,8 +395,9 @@ pub unsafe extern "C" fn khash_clone_context(raw: *const ctx::CContext, out: *mu
/// Free a salt allocated with `khash_new_salt` /// Free a salt allocated with `khash_new_salt`
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn khash_free_salt(salt: *mut salt::FFI) -> i32 pub unsafe extern "C" fn khash_free_salt(salt: *mut c_void) -> i32
{ {
let salt = salt as *mut salt::FFI;
no_unwind!{ no_unwind!{
drop(salt::from_raw(salt)); drop(salt::from_raw(salt));
GENERIC_SUCCESS GENERIC_SUCCESS
@ -394,8 +406,9 @@ pub unsafe extern "C" fn khash_free_salt(salt: *mut salt::FFI) -> i32
/// Create a new salt /// Create a new salt
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn khash_new_salt(salt_type: u8, bin: *const c_void, sz: size_t, nptr: *mut salt::FFI) -> i32 pub unsafe extern "C" fn khash_new_salt(salt_type: u8, bin: *const c_void, sz: size_t, nptr: *mut c_void) -> i32
{ {
let nptr = nptr as *mut salt::FFI;
no_unwind!{ no_unwind!{
try error::Error::Unknown; try error::Error::Unknown;
match salt_type { match salt_type {
@ -422,8 +435,10 @@ pub unsafe extern "C" fn khash_new_salt(salt_type: u8, bin: *const c_void, sz: s
/// Clone a salt /// Clone a salt
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn khash_clone_salt(salt: *const salt::FFI, out: *mut salt::FFI) -> i32 pub unsafe extern "C" fn khash_clone_salt(salt: *const c_void, out: *mut c_void) -> i32
{ {
let salt = salt as *const salt::FFI;
let out = out as *mut salt::FFI;
no_unwind!{ no_unwind!{
*out = salt::into_raw(salt::clone_from_raw(salt)); *out = salt::into_raw(salt::clone_from_raw(salt));
GENERIC_SUCCESS GENERIC_SUCCESS

@ -13,10 +13,13 @@ use std::{
convert::{TryInto,TryFrom}, convert::{TryInto,TryFrom},
}; };
/// The static salt size
pub const SIZE: usize = 32; pub const SIZE: usize = 32;
/// The default static salt
const STATIC_SALT: &[u8; SIZE] = &hex!("6787f049791466d5a31a3aa6f7138d8fbb907fd1785758298b5c97b0f3fb31ff"); const STATIC_SALT: &[u8; SIZE] = &hex!("6787f049791466d5a31a3aa6f7138d8fbb907fd1785758298b5c97b0f3fb31ff");
/// A salt to use for the kana-hash algorithm
#[derive(Clone,PartialEq,Eq,Hash,Debug)] #[derive(Clone,PartialEq,Eq,Hash,Debug)]
pub enum Salt pub enum Salt
{ {
@ -36,10 +39,12 @@ impl Default for Salt
impl Salt impl Salt
{ {
/// A fixed size salt of [SIZE]
pub fn fixed(array: [u8; SIZE]) -> Self pub fn fixed(array: [u8; SIZE]) -> Self
{ {
Self::Fixed(array) Self::Fixed(array)
} }
/// A salt from a slice
pub fn unfixed<T>(slice: &T) -> Self pub fn unfixed<T>(slice: &T) -> Self
where T: AsRef<[u8]> + ?Sized where T: AsRef<[u8]> + ?Sized
{ {
@ -47,21 +52,25 @@ impl Salt
assert!(slice.len() > 0, "Salt expects at least one byte."); assert!(slice.len() > 0, "Salt expects at least one byte.");
Self::Dynamic(Vec::from(slice).into_boxed_slice()) Self::Dynamic(Vec::from(slice).into_boxed_slice())
} }
pub fn none() -> Self /// No salt
pub const fn none() -> Self
{ {
Self::None Self::None
} }
/// Try to create a random salt
pub fn random() -> Result<Self, Error> pub fn random() -> Result<Self, Error>
{ {
let mut buffer = [0u8; SIZE]; let mut buffer = [0u8; SIZE];
getrandom(&mut buffer[..])?; getrandom(&mut buffer[..])?;
Ok(Self::Fixed(buffer)) Ok(Self::Fixed(buffer))
} }
/// The default internal salt
pub const fn internal() -> Self pub const fn internal() -> Self
{ {
Self::Static(STATIC_SALT) Self::Static(STATIC_SALT)
} }
/// Get the raw bytes of this salt
pub fn bytes(&self) -> &[u8] pub fn bytes(&self) -> &[u8]
{ {
match &self { match &self {
@ -81,22 +90,22 @@ impl Salt
#[derive(Copy,Clone,Debug)] #[derive(Copy,Clone,Debug)]
#[repr(C)] #[repr(C)]
pub struct FFI pub(crate) struct FFI
{ {
salt_type: u8, salt_type: u8,
size: u32, size: u32,
body: *mut u8, body: *mut u8,
} }
pub const SALT_TYPE_NONE: u8 = 0; pub(crate) const SALT_TYPE_NONE: u8 = 0;
pub const SALT_TYPE_DEFAULT: u8 = 1; pub(crate) const SALT_TYPE_DEFAULT: u8 = 1;
pub const SALT_TYPE_SPECIFIC: u8 = 2; pub(crate) const SALT_TYPE_SPECIFIC: u8 = 2;
pub const SALT_TYPE_RANDOM: u8 = 3; pub(crate) const SALT_TYPE_RANDOM: u8 = 3;
/// We won't try to copy more than this much data. /// We won't try to copy more than this much data.
const MAX_FFI_SALT_SIZE: usize = 1024; const MAX_FFI_SALT_SIZE: usize = 1024;
/// Clone a new `Salt` from an `FFI` salt. /// Clone a new `Salt` from an `FFI` salt.
pub unsafe fn clone_from_raw(ptr: *const FFI) -> Salt pub(crate) unsafe fn clone_from_raw(ptr: *const FFI) -> Salt
{ {
let ffi = &*ptr; let ffi = &*ptr;
match ffi.salt_type { match ffi.salt_type {
@ -110,7 +119,7 @@ pub unsafe fn clone_from_raw(ptr: *const FFI) -> Salt
} }
} }
/// Consume an `FFI` salt and return a `Salt`. /// Consume an `FFI` salt and return a `Salt`.
pub unsafe fn from_raw(ptr: *mut FFI) -> Salt pub(crate) unsafe fn from_raw(ptr: *mut FFI) -> Salt
{ {
let ffi = &mut *ptr; let ffi = &mut *ptr;
let out = match ffi.salt_type { let out = match ffi.salt_type {
@ -129,7 +138,7 @@ pub unsafe fn from_raw(ptr: *mut FFI) -> Salt
} }
/// Consume a `Salt` and output a new `FFI` salt. /// Consume a `Salt` and output a new `FFI` salt.
pub unsafe fn into_raw(salt: Salt) -> FFI pub(crate) unsafe fn into_raw(salt: Salt) -> FFI
{ {
unsafe fn allocate(slice: impl AsRef<[u8]>) -> FFI unsafe fn allocate(slice: impl AsRef<[u8]>) -> FFI
{ {

@ -0,0 +1,35 @@
use crate::*;
/// A streaming kana hash digest
pub struct Digest<'a, T>
where T: Read
{
input: &'a mut T,
}
impl<'a, T: Read> Digest<'a, T>
{
/// Create a new stream digest from the input
pub fn new(input: &'a mut T) -> Self
{
Self{input}
}
}
impl<'a, T: Read> Iterator for Digest<'a, T>
{
type Item = String;
fn next(&mut self) -> Option<Self::Item>
{
let mut buffer = [0u8; 2];
let mut rd =0;
while rd < 2 {
match self.input.read(&mut buffer[rd..]) {
Ok(2) => break,
Err(_) | Ok(0) => return None,
Ok(v) => rd+=v,
}
}
Some(format!("{}",mnemonic::Digest::new(&buffer[..])))
}
}
Loading…
Cancel
Save