rework with context

pull/1/head
Avril 4 years ago
parent c8ac1120ad
commit 2725851a6b
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -10,18 +10,19 @@
int main(void) int main(void)
{ {
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
const char* string = "hello world!"; const char* string = "hello world!";
printf("input: %s\n", string); printf("input: %s\n", string);
khash_salt salt; khash_ctx ctx;
assert(khash_new_salt(KHASH_SALT_TYPE_RANDOM, NULL, 0, &salt) == KHASH_SUCCESS); assert(khash_new_context(KHASH_ALGO_SHA256, KHASH_SALT_TYPE_NONE, NULL, 0, &ctx) == KHASH_SUCCESS);
printf("salt: %d\n", (int)salt.size); printf("salt: %d\n", (int)ctx.salt.size);
size_t length; size_t length;
assert(khash_length(string, strlen(string), &salt, &length) == KHASH_SUCCESS); assert(khash_length(&ctx, string, strlen(string), &length) == KHASH_SUCCESS);
printf("length: %d\n", (int)length); printf("length: %d\n", (int)length);
char* output = alloca(length+1); char* output = alloca(length+1);
assert(khash_do(string, strlen(string), &salt, output,length) == KHASH_SUCCESS); assert(khash_do(&ctx, string, strlen(string), output,length) == KHASH_SUCCESS);
output[length] = 0;
printf("output: %s\n", output); printf("output: %s\n", output);
return 0; return 0;
} }
@ -29,27 +30,27 @@ int main(void)
#define KTRY(expr, msg) (assert(((expr) && (msg))== KHASH_SUCCESS)) #define KTRY(expr, msg) (assert(((expr) && (msg))== KHASH_SUCCESS))
void k_do(const char* input, const khash_salt* salt) void k_do(const khash_ctx* ctx, const char* input)
{ {
khash_salt clone; khash_ctx clone;
KTRY(khash_clone_salt(salt, &clone), "khash: saltclone failed"); KTRY(khash_clone_context(ctx, &clone), "khash: ctxclone failed");
size_t length; size_t length;
KTRY(khash_length(input, strlen(input), &clone, &length), "khash: hashlength failed"); KTRY(khash_length(&clone, input, strlen(input), &length), "khash: hashlength failed");
char* output =alloca(length+1); char* output =alloca(length+1);
KTRY(khash_do(input,strlen(input), &clone, output, length), "khash: hashstring failed"); KTRY(khash_do(&clone, input,strlen(input), output, length), "khash: hashstring failed");
output[length] = 0; //ensure no overflow. output[length] = 0; //ensure no overflow.
printf("%s\n", output); printf("%s\n", output);
} }
void reseed_salt(khash_salt* salt, uint8_t type, const void* in_ptr, size_t ptr_sz) void reseed_ctx(khash_ctx* ctx, uint8_t algo, uint8_t type, const void* in_ptr, size_t ptr_sz)
{ {
KTRY(khash_free_salt(salt), "khash: saltrefree failed"); KTRY(khash_free_context(ctx), "khash: ctxrefree failed");
KTRY(khash_new_salt(type, in_ptr, ptr_sz, salt), "khash: saltreseed failed"); KTRY(khash_new_context(algo, type, in_ptr, ptr_sz, ctx), "khash: ctxreseed failed");
} }
static int _main(int argc, char** argv, khash_salt salt) static int _main(int argc, char** argv, khash_ctx ctx)
{ {
int look = 1; int look = 1;
if (argc <= 1) if (argc <= 1)
@ -64,16 +65,43 @@ static int _main(int argc, char** argv, khash_salt salt)
if (strcmp(*argv, "--help") == 0) if (strcmp(*argv, "--help") == 0)
{ {
printf("kana-hash cli\n"); printf("kana-hash cli\n");
printf("Usage: khash [--salt SALT-TYPE [<salt>]] [--] <input strings...>\n"); printf("Usage: khash [--algo ALGO] [--salt SALT-TYPE [<salt>]] [--] <input strings...>\n");
printf(" --algo: Specify the algorithm. (default crc64)\n");
printf(" ALGO: 3: crc32.\n");
printf(" ALGO: 6: crc64.\n");
printf(" ALGO: s: sha256.\n");
printf(" --salt: Specify the salt.\n"); printf(" --salt: Specify the salt.\n");
printf(" SALT_TYPE: D: default embedded.\n"); printf(" SALT_TYPE: D: default embedded.\n");
printf(" : N: no salt.\n"); printf(" : N: no salt.\n");
printf(" : R: random salt.\n");
printf(" : S <salt>: specific salt.\n"); printf(" : S <salt>: specific salt.\n");
printf(" --: Stop reading args here.\n"); printf(" --: Stop reading args here.\n");
return 1; return 1;
} }
else if (strcmp(*argv, "--") == 0) else if (strcmp(*argv, "--") == 0)
look = 0; look = 0;
else if (strcmp(*argv, "--algo")==0)
{
if (argv[1])
{
switch(argv[1][0])
{
case '3':
ctx.algo = KHASH_ALGO_CRC32;
break;
case '6':
ctx.algo = KHASH_ALGO_CRC64;
break;
case 's':
ctx.algo = KHASH_ALGO_SHA256;
break;
default:
fprintf(stderr, "ALGO: unknow algorithm key `%c'\n", *argv[1]);
return 1;
}
}
argv++;
}
else if (strcmp(*argv, "--salt")==0) else if (strcmp(*argv, "--salt")==0)
{ {
if (argv[1]) if (argv[1])
@ -82,22 +110,26 @@ static int _main(int argc, char** argv, khash_salt salt)
{ {
case 'd': case 'd':
case 'D': case 'D':
reseed_salt(&salt, KHASH_SALT_TYPE_DEFAULT, NULL, 0); reseed_ctx(&ctx, ctx.algo, KHASH_SALT_TYPE_DEFAULT, NULL, 0);
break; break;
case 'N': case 'N':
case 'n': case 'n':
reseed_salt(&salt, KHASH_SALT_TYPE_NONE, NULL, 0); reseed_ctx(&ctx, ctx.algo, KHASH_SALT_TYPE_NONE, NULL, 0);
break; break;
case 'S': case 'S':
case 's': case 's':
if(argv[2]) if(argv[2])
reseed_salt(&salt, KHASH_SALT_TYPE_SPECIFIC, argv[2], strlen(argv[2])); reseed_ctx(&ctx, ctx.algo, KHASH_SALT_TYPE_SPECIFIC, argv[2], strlen(argv[2]));
else { else {
fprintf(stderr, "SALT_TYPE `%c' expects a value.\n", *argv[1]); fprintf(stderr, "SALT_TYPE `%c' expects a value.\n", *argv[1]);
return 1; return 1;
} }
argv++; argv++;
break; break;
case 'R':
case 'r':
reseed_ctx(&ctx, ctx.algo, KHASH_SALT_TYPE_RANDOM, NULL, 0);
break;
default: default:
fprintf(stderr, "Unknown SALT_TYPE `%c'\n", *argv[1]); fprintf(stderr, "Unknown SALT_TYPE `%c'\n", *argv[1]);
return 1; return 1;
@ -111,7 +143,7 @@ static int _main(int argc, char** argv, khash_salt salt)
} }
else { else {
work: work:
k_do(*argv, &salt); k_do(&ctx, *argv);
} }
} }
@ -120,13 +152,14 @@ static int _main(int argc, char** argv, khash_salt salt)
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
setlocale(LC_ALL, "");
khash_salt salt;
KTRY(khash_new_salt(KHASH_SALT_TYPE_DEFAULT, NULL, 0, &salt), "khash: saltgen failed"); khash_ctx context;
KTRY(khash_new_context(KHASH_ALGO_DEFAULT, KHASH_SALT_TYPE_DEFAULT, NULL, 0, &context), "khash: ctxgen failed");
int res = _main(argc, argv, salt); int res = _main(argc, argv, context);
KTRY(khash_free_salt(&salt), "khash: saltfree failed"); KTRY(khash_free_context(&context), "khash: ctxfree failed");
return res; return res;
} }

@ -7,6 +7,11 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
#define KHASH_ALGO_DEFAULT ((uint8_t)0)
#define KHASH_ALGO_CRC32 ((uint8_t)1)
#define KHASH_ALGO_CRC64 ((uint8_t)2)
#define KHASH_ALGO_SHA256 ((uint8_t)3)
/// No salt /// No salt
#define KHASH_SALT_TYPE_NONE ((uint8_t)0) #define KHASH_SALT_TYPE_NONE ((uint8_t)0)
/// The default static salt /// The default static salt
@ -16,13 +21,19 @@ extern "C" {
/// A randomly generated salt. /// A randomly generated salt.
#define KHASH_SALT_TYPE_RANDOM ((uint8_t)3) #define KHASH_SALT_TYPE_RANDOM ((uint8_t)3)
/// A valid salt for khash functions. Initialised with `khash_new_salt`. /// A valid salt for khash functions. Instantiated with `khash_new_salt`.
typedef struct { typedef struct {
uint8_t salt_type; uint8_t salt_type;
uint32_t size; uint32_t size;
uint8_t* body; uint8_t* body;
} khash_salt; } khash_salt;
/// A valid context for khash functinos. Instantiated with `khash_new_context`.
typedef struct {
uint8_t algo;
khash_salt salt;
} khash_ctx;
/// Returned by all functions that succeed. /// Returned by all functions that succeed.
#define KHASH_SUCCESS ((int32_t)0) #define KHASH_SUCCESS ((int32_t)0)
@ -44,10 +55,15 @@ extern "C" {
extern int32_t khash_free_salt(khash_salt* salt); extern int32_t khash_free_salt(khash_salt* salt);
/// Clone a salt allocated with `khash_new_salt`. /// Clone a salt allocated with `khash_new_salt`.
extern int32_t khash_clone_salt(const khash_salt* src, khash_salt* dst); extern int32_t khash_clone_salt(const khash_salt* src, khash_salt* dst);
extern int32_t khash_new_context(uint8_t algo, uint8_t salt_type, const void* data, size_t size, khash_ctx* output);
extern int32_t khash_free_context(khash_ctx* ctx);
extern int32_t khash_clone_context(const khash_ctx* src, khash_ctx* dst);
/// Compute the length of hash required for the specified input. /// Compute the length of hash required for the specified input.
extern int32_t khash_length(const void* data, size_t size, const khash_salt* salt, size_t* length); extern int32_t khash_length(const khash_ctx* context, const void* data, size_t size, size_t* length);
/// Compute the hash and store it in `string`. Will write no more than `strlen` bytes into `string`. /// Compute the hash and store it in `string`. Will write no more than `strlen` bytes into `string`.
extern int32_t khash_do(const void* data, size_t size, khash_salt* salt, char* string, size_t strlen); extern int32_t khash_do(khash_ctx* context, const void* data, size_t size, char* string, size_t strlen);
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -1,10 +1,11 @@
use crate::*; use crate::*;
use std::{
io::{
Read,
},
};
pub const ALGO_CRC32: u8 = 0; #[derive(Clone,Debug,PartialEq,Eq,Hash)]
pub const ALGO_CRC64: u8 = 1;
pub const ALGO_SHA256: u8 = 2;
#[derive(Debug,PartialEq,Eq,Hash)]
pub enum Algorithm pub enum Algorithm
{ {
Crc32, Crc32,
@ -12,19 +13,135 @@ pub enum Algorithm
Sha256, Sha256,
} }
impl Default for Algorithm
{
fn default() -> Self
{
Self::Crc64
}
}
#[derive(Clone,Debug,PartialEq,Eq,Hash)]
pub struct Context pub struct Context
{ {
algo: Algorithm, algo: Algorithm,
salt: salt::Salt, salt: salt::Salt,
}
impl Context
{
pub fn new(algo: Algorithm, salt: impl Into<salt::Salt>) -> Self
{
Self {
algo,
salt: salt.into(),
}
}
pub fn get_algorithm(&self) -> &Algorithm
{
&self.algo
}
pub fn get_salt(&self) -> &salt::Salt
{
&self.salt
}
pub 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,
R: Read + ?Sized
{
let this = P::compute(input, &salt, output)?;
Ok(Vec::from(this.bytes()))
}
let mut output = 0usize;
let bytes = match self.algo
{
Algorithm::Crc32 => provide::<hash::Crc32Checksum, _>(&mut from, &self.salt, &mut output)?,
Algorithm::Crc64 => provide::<hash::Crc64Checksum, _>(&mut from, &self.salt, &mut output)?,
Algorithm::Sha256 => provide::<hash::Sha256Hash, _>(&mut from, &self.salt, &mut output)?,
}.into_boxed_slice();
Ok((output, bytes))
}
pub unsafe fn into_raw(self) -> CContext
{
CContext{
algo: u8::from(self.algo),
salt: salt::into_raw(self.salt),
}
}
pub unsafe fn clone_from_raw(from: *const CContext) -> Self
{
let from = &*from;
Self {
algo: from.algo.into(),
salt: salt::clone_from_raw(&from.salt as *const salt::FFI),
}
}
pub unsafe fn from_raw(from: *mut CContext) -> Self
{
let from = &mut *from;
let output = Self{
algo: from.algo.into(),
salt: salt::from_raw(&mut from.salt as *mut salt::FFI),
};
from.algo = 0;
output
}
} }
impl Default for Context
{
fn default() -> Self
{
Self {
algo: Default::default(),
salt: Default::default(),
}
}
}
pub const ALGO_DEFAULT: u8 = 0;
pub const ALGO_CRC32: u8 = 1;
pub const ALGO_CRC64: u8 = 2;
pub const ALGO_SHA256: u8 = 3;
/// FFI context /// FFI context
#[derive(Debug)] #[derive(Debug)]
#[repr(C)] #[repr(C)]
pub struct CContext pub struct CContext
{ {
algo: u8, algo: u8,
salt: *mut salt::FFI, salt: salt::FFI,
} }
impl From<Algorithm> for u8
{
fn from(al: Algorithm) -> Self
{
match al {
Algorithm::Crc32 => ALGO_CRC32,
Algorithm::Crc64 => ALGO_CRC64,
Algorithm::Sha256 => ALGO_SHA256,
}
}
}
impl From<u8> for Algorithm
{
fn from(al: u8) -> Self
{
match al {
ALGO_CRC32 => Algorithm::Crc32,
ALGO_CRC64 => Algorithm::Crc64,
ALGO_SHA256 => Algorithm::Sha256,
_ => Self::default(),
}
}
}

@ -16,7 +16,8 @@ mod tests {
fn it_works() -> Result<(), error::Error> fn it_works() -> Result<(), error::Error>
{ {
let input = b"lolis are super ultra mega cute"; let input = b"lolis are super ultra mega cute";
let kana = generate(input, salt::Salt::default())?; let context = ctx::Context::default();
let kana = generate(&context, input)?;
println!("kana: {}", kana); println!("kana: {}", kana);
assert_eq!(kana, "ワイトひはっトと"); assert_eq!(kana, "ワイトひはっトと");
Ok(()) Ok(())
@ -24,7 +25,7 @@ mod tests {
#[test] #[test]
fn ffi() -> Result<(), Box<dyn std::error::Error>> fn ffi() -> Result<(), Box<dyn std::error::Error>>
{ {
Ok(()) Ok(())
} }
} }
@ -45,17 +46,19 @@ mod hash;
mod provider; mod provider;
mod mnemonic; mod mnemonic;
mod error; mod error;
mod ctx;
#[macro_use] #[macro_use]
mod ffi; mod ffi;
use ffi::*; use ffi::*;
fn compute<T: Read, Digest: provider::ByteProvider>(mut from: T, salt: salt::Salt) -> Result<(usize, String), error::Error> fn compute<T: Read>(context: &ctx::Context, mut from: T) -> Result<(usize, String), error::Error>
{ {
let (read, hash) = provider::compute::<_, Digest>(&mut from, salt)?; //let (read, hash) = provider::compute::<_, Digest>(&mut from, salt)?;
let (read, hash) = context.compute(&mut from)?;
let mut output = String::with_capacity(128); let mut output = String::with_capacity(128);
for element in hash.bytes().iter() for element in hash.into_iter()
.into_16() .into_16()
.map(|bytes| mnemonic::Digest::new(unsafe{reinterpret::bytes(&bytes)})) .map(|bytes| mnemonic::Digest::new(unsafe{reinterpret::bytes(&bytes)}))
{ {
@ -65,11 +68,11 @@ fn compute<T: Read, Digest: provider::ByteProvider>(mut from: T, salt: salt::Sal
Ok((read,output)) Ok((read,output))
} }
pub fn generate<T: AsRef<[u8]>>(bytes: T, salt: salt::Salt) -> 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();
let mut nbytes = bytes; let mut nbytes = bytes;
let (ok, string) = compute::<_, HASHER>(&mut nbytes,salt)?; let (ok, string) = compute(context, &mut nbytes)?;
if ok == bytes.len() { if ok == bytes.len() {
Ok(string) Ok(string)
} else { } else {
@ -94,12 +97,13 @@ use malloc_array::{
/// # Note /// # Note
/// Does not consume `salt` /// Does not consume `salt`
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn khash_length(bin: *const c_void, sz: size_t, salt: *const salt::FFI, out_len: *mut size_t) -> i32 pub unsafe extern "C" fn khash_length(context: *const ctx::CContext, bin: *const c_void, sz: size_t, out_len: *mut size_t) -> i32
{ {
no_unwind!{ no_unwind!{
try error::Error::Unknown; try error::Error::Unknown;
let context = ctx::Context::clone_from_raw(context);
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz)); let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
let string = c_try!(generate(&bin, salt::clone_from_raw(salt))); let string = c_try!(generate(&context, &bin));
*out_len = string.bytes().len().into(); *out_len = string.bytes().len().into();
GENERIC_SUCCESS GENERIC_SUCCESS
@ -111,12 +115,14 @@ pub unsafe extern "C" fn khash_length(bin: *const c_void, sz: size_t, salt: *con
/// # Note /// # Note
/// Consumes `salt` /// Consumes `salt`
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn khash_do(bin: *const c_void, sz: size_t, salt: *mut salt::FFI, out_str: *mut c_char, str_len: size_t) -> i32 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
{ {
no_unwind!{ no_unwind!{
try error::Error::Unknown; try error::Error::Unknown;
let context = ctx::Context::from_raw(context);
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz)); let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
let string: Vec<u8> = c_try!(generate(&bin, salt::from_raw(salt))).bytes().collect(); let string: Vec<u8> = c_try!(generate(&context, &bin)).bytes().collect();
libc::memcpy(out_str as *mut c_void, &string[0] as *const u8 as *const c_void, std::cmp::min(str_len, string.len())); libc::memcpy(out_str as *mut c_void, &string[0] as *const u8 as *const c_void, std::cmp::min(str_len, string.len()));
@ -124,6 +130,57 @@ pub unsafe extern "C" fn khash_do(bin: *const c_void, sz: size_t, salt: *mut sal
} }
} }
/// Free a context
#[no_mangle]
pub unsafe extern "C" fn khash_free_context(context: *mut ctx::CContext) -> i32
{
no_unwind!{
drop(ctx::Context::from_raw(context));
GENERIC_SUCCESS
}
}
/// 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
{
no_unwind!{
try error::Error::Unknown;
let salt = match salt_type {
salt::SALT_TYPE_SPECIFIC => {
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
salt::Salt::unfixed(&bin[..])
},
salt::SALT_TYPE_DEFAULT => {
salt::Salt::default()
},
salt::SALT_TYPE_RANDOM => {
match salt::Salt::random() {
Ok(v) => v,
Err(e) => return i32::from(error::Error::RNG(e)),
}
},
_ => {
salt::Salt::None
},
};
let context = ctx::Context::new(algo.into(), salt);
*nptr = context.into_raw();
GENERIC_SUCCESS
}
}
/// Clone a context
#[no_mangle]
pub unsafe extern "C" fn khash_clone_context(raw: *const ctx::CContext, out: *mut ctx::CContext) -> i32
{
no_unwind!{
*out = ctx::Context::clone_from_raw(raw).into_raw();
GENERIC_SUCCESS
}
}
/// 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 salt::FFI) -> i32
@ -162,6 +219,7 @@ pub unsafe extern "C" fn khash_new_salt(salt_type: u8, bin: *const c_void, sz: s
} }
} }
/// 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 salt::FFI, out: *mut salt::FFI) -> i32
{ {

Loading…
Cancel
Save