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)]
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)]
pub struct Context
{
@ -31,6 +33,7 @@ pub struct 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
{
Self {
@ -38,16 +41,20 @@ impl Context
salt: salt.into(),
}
}
/// The algorithm used
pub fn get_algorithm(&self) -> &Algorithm
{
&self.algo
}
/// The salt used
pub fn get_salt(&self) -> &salt::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>
where P: provider::ByteProvider,
@ -69,7 +76,7 @@ impl Context
Ok((output, bytes))
}
pub unsafe fn into_raw(self) -> CContext
pub(crate) unsafe fn into_raw(self) -> CContext
{
CContext{
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;
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 output = Self{
@ -110,16 +117,16 @@ impl Default for Context
}
}
pub const ALGO_DEFAULT: u8 = 0;
pub const ALGO_CRC32: u8 = 1;
pub const ALGO_CRC64: u8 = 2;
pub const ALGO_SHA256: u8 = 3;
pub const ALGO_SHA256_TRUNCATED: u8 = 4;
pub(crate) const ALGO_DEFAULT: u8 = 0;
pub(crate) const ALGO_CRC32: u8 = 1;
pub(crate) const ALGO_CRC64: u8 = 2;
pub(crate) const ALGO_SHA256: u8 = 3;
pub(crate) const ALGO_SHA256_TRUNCATED: u8 = 4;
/// FFI context
#[derive(Debug)]
#[repr(C)]
pub struct CContext
pub(crate) struct CContext
{
algo: u8,
flags: u64, //nothing yet, might be flags later idk

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

@ -242,12 +242,14 @@ mod sixteen;
use sixteen::Bit16IterExt;
mod def;
mod map;
mod salt;
pub mod salt;
mod hash;
mod provider;
mod mnemonic;
mod error;
mod ctx;
pub mod error;
pub mod ctx;
mod stream;
pub use stream::Digest;
#[macro_use]
mod ffi;
@ -269,6 +271,7 @@ fn compute<T: Read>(context: &ctx::Context, mut from: T) -> Result<(usize, Strin
Ok((read,output))
}
/// Generate kana hash from a slice.
pub fn generate<T: AsRef<[u8]>>(context: &ctx::Context, bytes: T) -> Result<String, error::Error>
{
let bytes = bytes.as_ref();
@ -291,6 +294,8 @@ use malloc_array::{
HeapArray,
};
// FFI section
/// Calculate the length in bytes of a kana hash output.
@ -298,8 +303,9 @@ use malloc_array::{
/// # Note
/// Does not consume `salt`
#[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!{
try error::Error::Unknown;
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
/// Consumes `salt`
#[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!{
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
#[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!{
drop(ctx::Context::from_raw(context));
GENERIC_SUCCESS
@ -343,8 +351,9 @@ pub unsafe extern "C" fn khash_free_context(context: *mut ctx::CContext) -> i32
/// Create a new context
#[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!{
try error::Error::Unknown;
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
#[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!{
*out = ctx::Context::clone_from_raw(raw).into_raw();
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`
#[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!{
drop(salt::from_raw(salt));
GENERIC_SUCCESS
@ -394,8 +406,9 @@ pub unsafe extern "C" fn khash_free_salt(salt: *mut salt::FFI) -> i32
/// Create a new salt
#[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!{
try error::Error::Unknown;
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
#[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!{
*out = salt::into_raw(salt::clone_from_raw(salt));
GENERIC_SUCCESS

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

@ -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