pull/1/head
Avril 4 years ago
parent fe3381650e
commit 0d99d6664b
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -13,3 +13,5 @@ sha2 = "0.9"
malloc-array = "1.3.3"
libc = "0.2"
crc = "1.8"
hex-literal = "0.2"
getrandom = "0.1"

@ -10,6 +10,7 @@ pub enum Error
IO(io::Error),
Format(fmt::Error),
Length{expected: usize, got:usize,},
RNG(getrandom::Error),
Unknown,
}
@ -20,6 +21,7 @@ impl error::Error for Error
match &self {
Error::IO(e_io) => Some(e_io),
Error::Format(e_fmt) => Some(e_fmt),
Error::RNG(e_rng) => Some(e_rng),
_ => None,
}
}
@ -34,6 +36,7 @@ impl fmt::Display for Error
Error::IO(io) => write!(f, "io: {}", io),
Error::Format(fmt) => write!(f, "fmt: {}", fmt),
Error::Length{expected, got} => write!(f, "invalid length: expected {}, got {}", expected, got),
Error::RNG(rng) => write!(f, "rng error: {}", rng),
_ => write!(f, "unknown failure"),
}
}
@ -47,6 +50,7 @@ impl From<Error> for i32
Error::IO(_) => 1,
Error::Format(_) => 2,
Error::Length{..} => 3,
Error::RNG(_) => 4,
_ => -1,
}
}
@ -66,3 +70,11 @@ impl From<fmt::Error> for Error
Self::Format(i)
}
}
impl From<getrandom::Error> for Error
{
fn from(rng: getrandom::Error) -> Self
{
Self::RNG(rng)
}
}

@ -0,0 +1,26 @@
use crate::*;
pub trait HeapArrayExt: Sized
{
fn into_unsafe(self) -> Self;
fn into_safe(self) -> Self;
fn set_unsafe(self, un: bool) -> Self;
}
impl<T> HeapArrayExt for HeapArray<T>
{
fn into_unsafe(mut self) -> Self
{
self.drop_check = false;
self
}
fn into_safe(mut self) -> Self
{
self.drop_check = true;
self
}
fn set_unsafe(mut self, un: bool) -> Self
{
self.drop_check = un;
self
}
}

@ -13,7 +13,7 @@ impl provider::ByteProvider for Crc32Checksum
unsafe{reinterpret::bytes(&self.hash)}
}
fn compute<T: Read + ?Sized>(input: &mut T, done: &mut usize) -> Result<Self, error::Error>
fn compute<T: Read + ?Sized>(input: &mut T, salt: &salt::Salt, done: &mut usize) -> Result<Self, error::Error>
{
let mut buffer = [0u8; BUFFER_SIZE];
let mut hasher = crc32::Digest::new(crc32::IEEE);
@ -23,6 +23,7 @@ impl provider::ByteProvider for Crc32Checksum
hasher.write(&buffer[..read]);
*done += read;
}
hasher.write(salt.bytes());
Ok(Self{hash: hasher.sum32()})
}
}

@ -13,7 +13,7 @@ impl provider::ByteProvider for Crc64Checksum
unsafe{reinterpret::bytes(&self.hash)}
}
fn compute<T: Read + ?Sized>(input: &mut T, done: &mut usize) -> Result<Self, error::Error>
fn compute<T: Read + ?Sized>(input: &mut T, salt: &salt::Salt, done: &mut usize) -> Result<Self, error::Error>
{
let mut buffer = [0u8; BUFFER_SIZE];
let mut hasher = crc64::Digest::new(crc64::ECMA);
@ -23,6 +23,7 @@ impl provider::ByteProvider for Crc64Checksum
hasher.write(&buffer[..read]);
*done += read;
}
hasher.write(salt.bytes());
Ok(Self{hash: hasher.sum64()})
}
}

@ -34,13 +34,14 @@ fn compute_stream<T: Read +?Sized, D: Digest>(input: &mut T, output: &mut D) ->
impl Sha256Hash
{
/// Compute a hash from a stream.
pub fn compute<T: Read + ?Sized>(input: &mut T) -> io::Result<(usize, Self)>
pub fn compute<T: Read + ?Sized>(input: &mut T, salt: &salt::Salt) -> io::Result<(usize, Self)>
{
let mut hash = [0u8; SHA256_SIZE];
let mut hasher = Sha256::new();
let ok = compute_stream(input, &mut hasher)?;
hasher.update(salt.bytes());
assert_eq!(array::copy_slice(&mut hash, hasher.finalize()), SHA256_SIZE);
Ok((ok, Self{hash}))
@ -74,9 +75,9 @@ impl provider::ByteProvider for hash::Sha256Hash
&self.bytes()[..]
}
fn compute<T: Read + ?Sized>(input: &mut T, done: &mut usize) -> Result<Self, error::Error>
fn compute<T: Read + ?Sized>(input: &mut T, salt: &salt::Salt, done: &mut usize) -> Result<Self, error::Error>
{
let (ok, this) = Self::compute(input)?;
let (ok, this) = Self::compute(input, salt)?;
*done = ok;
Ok(this)
}

@ -1,3 +1,4 @@
//#![feature(const_generics)]
#![allow(dead_code)]
use std::{
io::{
@ -6,7 +7,7 @@ use std::{
fmt::Write,
};
type HASHER =hash::Crc64Checksum;
type HASHER = hash::Crc64Checksum;
#[cfg(test)]
mod tests {
@ -14,10 +15,36 @@ mod tests {
#[test]
fn it_works() -> Result<(), error::Error>
{
let input = b"hello world!!";
let kana = generate(input)?;
let input = b"lolis are super ultra mega cute";
let kana = generate(input, salt::Salt::default())?;
println!("kana: {}", kana);
panic!("uhh")
assert_eq!(kana, "ワイトひはっトと");
Ok(())
}
#[test]
fn ffi() -> Result<(), Box<dyn std::error::Error>>
{
unsafe {
unsafe fn work_with_salt(salt: salt::Salt) -> Result<String, error::Error> {
let input = b"lolis are super ultra mega cute";
let salt = salt::into_raw(salt);
// Simulate ffi call;
let mut sz: libc::size_t = 0;
assert_eq!(GENERIC_SUCCESS, _kana_length(&input[0] as *const u8 as *const libc::c_void, input.len(), salt as *const libc::c_void, &mut sz as *mut size_t));
assert_eq!(sz, 24);
let mut output = malloc_array::heap![unsafe u8; sz];
assert_eq!(GENERIC_SUCCESS, _kana_do(&input[0] as *const u8 as *const libc::c_void, input.len(), salt as *mut libc::c_void, output.as_ptr_mut() as *mut libc::c_char, sz));
let string = std::str::from_utf8(&output[..]).unwrap();
Ok(string.to_owned())
}
assert_eq!("けほほぇほょすゆ", work_with_salt(salt::Salt::None)?);
assert_eq!("ワイトひはっトと", work_with_salt(salt::Salt::default())?);
}
Ok(())
}
}
@ -25,11 +52,14 @@ pub const BUFFER_SIZE: usize = 4096;
mod array;
mod reinterpret;
mod group;
mod ext;
use ext::*;
mod group; //unused
mod sixteen;
use sixteen::Bit16IterExt;
mod def;
mod map;
mod salt;
mod hash;
mod provider;
mod mnemonic;
@ -39,9 +69,9 @@ mod error;
mod ffi;
use ffi::*;
fn compute<T: Read, Digest: provider::ByteProvider>(mut from: T) -> Result<(usize, String), error::Error>
fn compute<T: Read, Digest: provider::ByteProvider>(mut from: T, salt: salt::Salt) -> Result<(usize, String), error::Error>
{
let (read, hash) = provider::compute::<_, Digest>(&mut from)?;
let (read, hash) = provider::compute::<_, Digest>(&mut from, salt)?;
println!("hash ({}): {}", read, hash);
let mut output = String::with_capacity(128);
@ -55,11 +85,11 @@ fn compute<T: Read, Digest: provider::ByteProvider>(mut from: T) -> Result<(usiz
Ok((read,output))
}
pub fn generate<T: AsRef<[u8]>>(bytes: T) -> Result<String, error::Error>
pub fn generate<T: AsRef<[u8]>>(bytes: T, salt: salt::Salt) -> Result<String, error::Error>
{
let bytes = bytes.as_ref();
let mut nbytes = bytes;
let (ok, string) = compute::<_, HASHER>(&mut nbytes)?;
let (ok, string) = compute::<_, HASHER>(&mut nbytes,salt)?;
if ok == bytes.len() {
Ok(string)
} else {
@ -77,28 +107,69 @@ use malloc_array::{
HeapArray,
};
// FFI section
/// Calculate the length in bytes of a kana hash output.
///
/// # Note
/// Does not consume `salt`
#[no_mangle]
pub unsafe extern "C" fn _kana_length(bin: *const c_void, sz: size_t, out_len: *mut size_t) -> i32
pub unsafe extern "C" fn _kana_length(bin: *const c_void, sz: size_t, salt: *const c_void, out_len: *mut size_t) -> i32
{
no_unwind!{
try error::Error::Unknown;
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
let string = c_try!(generate(&bin));
*out_len = (string.bytes().len()+1).into();
let string = c_try!(generate(&bin, salt::clone_from_raw(salt as *const salt::FFI)));
*out_len = string.bytes().len().into();
GENERIC_SUCCESS
}
}
/// Compute and write a kana hash output to a string.
///
/// # Note
/// Consumes `salt`
#[no_mangle]
pub unsafe extern "C" fn _kana_do(bin: *const c_void, sz: size_t, out_str: *mut c_char, str_len: size_t) -> i32
pub unsafe extern "C" fn _kana_do(bin: *const c_void, sz: size_t, salt: *mut c_void, out_str: *mut c_char, str_len: size_t) -> i32
{
no_unwind!{
try error::Error::Unknown;
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
let string: Vec<u8> = c_try!(generate(&bin)).bytes().collect();
let string: Vec<u8> = c_try!(generate(&bin, salt::from_raw(salt as *mut salt::FFI))).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()));
GENERIC_SUCCESS
}
}
/// Free a salt allocated with `_kana_new_salt`
#[no_mangle]
pub unsafe extern "C" fn _kana_free_salt(salt: *mut c_void) -> i32
{
no_unwind!{
drop(salt::from_raw(salt as *mut salt::FFI));
GENERIC_SUCCESS
}
}
/// Create a new salt
#[no_mangle]
pub unsafe extern "C" fn _kana_new_salt(bin: *const c_void, sz: size_t, nptr: *mut *const c_void) -> i32
{
no_unwind!{
try error::Error::Unknown;
let nptr = nptr as *mut *const salt::FFI;
if bin.is_null() {
*nptr = salt::into_raw(salt::Salt::default());
} else if sz == 0 {
*nptr = salt::into_raw(salt::Salt::None);
} else {
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
*nptr = salt::into_raw(salt::Salt::unfixed(&bin[..]));
}
GENERIC_SUCCESS
}
}

@ -21,12 +21,13 @@ impl Digest {
d.0 = Some(map::KANA[master]);
if from[1] > 0 {
if let Some(slaves) = map::sub(master) {
if slaves.len() > 0 {
let one = (usize::from(from[1]) / map::KANA.len()) % 2;
if slaves.len() > 0 && one > 0{
d.1 = Some(slaves[usize::from(from[1]) % slaves.len()]);
return d;
}
}
let from = [from[1]];
let from = [from[1], 0];
d.1 = Self::new(&from[..]).0;
}
d

@ -2,14 +2,14 @@ use crate::*;
pub trait ByteProvider: Sized + std::fmt::Display
{
fn compute<T: Read + ?Sized>(input: &mut T, provided: &mut usize) -> Result<Self, error::Error>;
fn compute<T: Read + ?Sized>(input: &mut T, salt: &salt::Salt, provided: &mut usize) -> Result<Self, error::Error>;
fn bytes(&self) -> &[u8];
}
pub fn compute<T: Read + ?Sized, P: ByteProvider>(input: &mut T) -> Result<(usize, P), error::Error>
pub fn compute<T: Read + ?Sized, P: ByteProvider>(input: &mut T, salt: salt::Salt) -> Result<(usize, P), error::Error>
{
let mut output = 0usize;
let this = P::compute(input, &mut output)?;
let this = P::compute(input, &salt, &mut output)?;
Ok((output, this))
}

@ -0,0 +1,150 @@
use crate::*;
use malloc_array::*;
use getrandom::{
getrandom,
Error,
};
use hex_literal::hex;
use std::{
io::{
self,
Write,
},
};
pub const SIZE: usize = 32;
const STATIC_SALT: &[u8; SIZE] = &hex!("6787f049791466d5a31a3aa6f7138d8fbb907fd1785758298b5c97b0f3fb31ff");
#[derive(Clone,PartialEq,Eq,Hash,Debug)]
pub enum Salt
{
None,
Static(&'static [u8; SIZE]),
Fixed([u8; SIZE]),
Dynamic(Box<[u8]>),
}
impl Default for Salt
{
fn default() -> Self
{
Self::Static(STATIC_SALT)
}
}
impl Salt
{
pub fn fixed(array: [u8; SIZE]) -> Self
{
Self::Fixed(array)
}
pub fn unfixed<T>(slice: &T) -> Self
where T: AsRef<[u8]> + ?Sized
{
let slice = slice.as_ref();
assert!(slice.len() > 0, "Salt expects at least one byte.");
Self::Dynamic(Vec::from(slice).into_boxed_slice())
}
pub fn none() -> Self
{
Self::None
}
pub fn random() -> Result<Self, Error>
{
let mut buffer = [0u8; SIZE];
getrandom(&mut buffer[..])?;
Ok(Self::Fixed(buffer))
}
pub const fn internal() -> Self
{
Self::Static(STATIC_SALT)
}
pub fn bytes(&self) -> &[u8]
{
match &self {
Self::Fixed(ar) => &ar[..],
Self::Dynamic(vec) => &vec[..],
Self::Static(s) => &s[..],
_ => &[],
}
}
/// Append salt bytes to a stream.
pub fn append<W: Write+?Sized>(&self, to: &mut W) -> io::Result<usize>
{
to.write(self.bytes())
}
}
#[derive(Copy,Clone,Debug)]
#[repr(C)]
#[repr(packed)]
pub struct FFI
{
size: usize,
body: *mut u8,
}
/// 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
{
if ptr.is_null() {
Salt::default()
} else {
let ptr = &*ptr;
if ptr.size == 0 || ptr.body.is_null() {
return Salt::None;
}
let size = std::cmp::min(ptr.size, MAX_FFI_SALT_SIZE);
Salt::Dynamic(HeapArray::from_raw_copied(ptr.body, size).into_unsafe().into_boxed_slice())
}
}
/// Consume an `FFI` salt and return a `Salt`.
pub unsafe fn from_raw(ptr: *mut FFI) -> Salt
{
if ptr.is_null() {
Salt::default()
} else {
let ptr = {
let mut ptr = HeapArray::from_raw_parts(ptr, 1);
let rval = ptr[0].clone();
ptr.set_memory(0);
rval
};
if ptr.size == 0 || ptr.body.is_null() {
return Salt::None;
}
let body = HeapArray::from_raw_parts(ptr.body, ptr.size);
Salt::Dynamic(body.into_boxed_slice())
}
}
/// Consume a `Salt` and output a newly allocated `FFI` salt.
pub unsafe fn into_raw(salt: Salt) -> *mut FFI
{
unsafe fn genffi(bytes: &[u8]) -> *mut FFI
{
if bytes.len() == 0 {
let (ffi, _) = heap![FFI{size:0,body:0 as *mut u8}].into_raw_parts();
ffi
} else {
let mut array = heap![unsafe u8; bytes.len()];
array.memory_from_raw(&bytes[0] as *const u8, bytes.len());
let (body, size) = array.into_raw_parts();
let (ffi, _) = heap![FFI{size,body}].into_raw_parts();
ffi
}
}
match salt {
Salt::Static(STATIC_SALT) => 0 as *mut FFI,
Salt::Static(&other) | Salt::Fixed(other) => genffi(&other[..]),
Salt::Dynamic(other) => genffi(&other[..]),
_ => genffi(salt.bytes()),
}
}
Loading…
Cancel
Save