cryptonote-raw-crypto 0.5.5

Cryptography Primitives for Cryptonote
Documentation
extern "C" {
  fn cn_slow_hash(data: *const u8, length: usize, hash: *mut u8, variant: usize, prehashed: usize);
  fn cn_fast_hash(data: *const u8, length: usize, hash: *mut u8);
  fn check_hash(hash: *const [u8; 32], difficulty: u64) -> bool;
}

pub struct Hash {}

impl Hash {
  pub fn fast(data: &[u8]) -> [u8; 32] {
    let mut hash: [u8; 32] = [0; 32];
    unsafe { cn_fast_hash(data.as_ptr(), data.len(), hash.as_mut_ptr()) }
    hash
  }
  pub fn slow(input: &Vec<u8>) -> [u8; 32] {
    return Hash::slow_with_variant(input, 0);
  }

  pub fn slow_with_variant(input: &Vec<u8>, variant: usize) -> [u8; 32] {
    let mut hash: [u8; 32] = [0; 32];
    unsafe {
      cn_slow_hash(input.as_ptr(), input.len(), hash.as_mut_ptr(), variant, 0);
    }
    hash
  }

  pub fn check_with_difficulty(hash: &[u8; 32], difficulty: u64) -> bool {
    unsafe {
      return check_hash(hash, difficulty);
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use std::fs::{canonicalize, File};
  use std::io::{prelude::*, BufReader};
  use std::path::PathBuf;

  #[test]
  fn should_check_hash_with_difficulty() {
    assert!(Hash::check_with_difficulty(
      &[
        0, 223, 74, 253, 65, 221, 188, 172, 253, 50, 122, 246, 173, 212, 162, 103, 13, 174, 254,
        199, 175, 49, 254, 177, 181, 91, 56, 9, 98, 1, 0, 0
      ],
      10343869
    ));
  }

  #[test]

  fn should_test_fast() {
    let path = PathBuf::from("./tests/tests-fast.txt");
    let str = canonicalize(path);
    let f = File::open(str.unwrap()).unwrap();
    let file = BufReader::new(&f);
    for (_num, line) in file.lines().enumerate() {
      let l = line.unwrap();
      let split: Vec<&str> = l.split_whitespace().collect();
      let expected = hex::decode(split[0]).expect("Error parse expected");
      let plain: Vec<u8>;
      if split[1] == "x" {
        plain = hex::decode("").expect("Error parse scalar");
      } else {
        plain = hex::decode(split[1]).expect("Error parse scalar");
      }
      let hash = Hash::fast(&plain);
      assert!(hash == expected.as_slice());
    }
  }

  #[test]

  fn should_test_slow() {
    let path = PathBuf::from("./tests/tests-slow.txt");
    let str = canonicalize(path);
    let f = File::open(str.unwrap()).unwrap();
    let file = BufReader::new(&f);
    for (_num, line) in file.lines().enumerate() {
      let l = line.unwrap();
      let split: Vec<&str> = l.split_whitespace().collect();
      let expected = hex::decode(split[0]).expect("Error parse expected");
      let plain: Vec<u8>;
      if split[1] == "x" {
        plain = hex::decode("").expect("Error parse scalar");
      } else {
        plain = hex::decode(split[1]).expect("Error parse scalar");
      }
      let hash = Hash::slow(&plain);
      assert!(hash == expected.as_slice());
    }
  }

  #[test]
  fn should_get_fast_hash() {
    let input = [
      0x01, 0x3c, 0x01, 0xff, 0x00, 0x01, 0x01, 0x02, 0x9b, 0x2e, 0x4c, 0x02, 0x81, 0xc0, 0xb0,
      0x2e, 0x7c, 0x53, 0x29, 0x1a, 0x94, 0xd1, 0xd0, 0xcb, 0xff, 0x88, 0x83, 0xf8, 0x02, 0x4f,
      0x51, 0x42, 0xee, 0x49, 0x4f, 0xfb, 0xbd, 0x08, 0x80, 0x71, 0x21, 0x01, 0xa9, 0xa4, 0x56,
      0x9f, 0x7e, 0x10, 0x16, 0x4a, 0x32, 0x32, 0x4b, 0x2b, 0x87, 0x8a, 0xe3, 0x2d, 0x98, 0xbe,
      0x09, 0x49, 0xce, 0x6e, 0x01, 0x50, 0xba, 0x1d, 0x7e, 0x54, 0xd6, 0x09, 0x69, 0xe5,
    ];
    let hash = Hash::fast(&input);
    assert!(
      hash
        == [
          81, 131, 30, 137, 17, 68, 149, 122, 23, 4, 105, 195, 35, 123, 221, 255, 230, 192, 96, 73,
          129, 38, 117, 210, 237, 178, 168, 52, 82, 247, 162, 80
        ]
    );

    let input = [
      50, 228, 229, 247, 39, 151, 194, 252, 14, 45, 218, 78, 128, 230, 27, 208, 9, 57, 52, 163, 5,
      175, 8, 201, 211, 185, 66, 113, 88, 68, 170, 8,
    ];
    let hash = Hash::fast(&input);
    assert!(
      hash
        == [
          197, 173, 69, 56, 117, 95, 205, 188, 226, 116, 198, 205, 121, 235, 248, 74, 211, 46, 177,
          65, 72, 147, 115, 194, 212, 214, 163, 109, 121, 3, 36, 249
        ]
    );
    let input = [50];
    let hash = Hash::fast(&input);
    assert!(
      hash
        == [
          173, 124, 91, 239, 2, 120, 22, 168, 0, 218, 23, 54, 68, 79, 181, 138, 128, 126, 244, 201,
          96, 59, 120, 72, 103, 63, 126, 58, 104, 235, 20, 165
        ]
    );
  }

  #[test]
  fn should_test_slow_hash() {
    let path = PathBuf::from("./tests/hash/tests-slow.txt");
    let str = canonicalize(path);
    let f = File::open(str.unwrap()).unwrap();
    let file = BufReader::new(&f);
    for (_num, line) in file.lines().enumerate() {
      let l = line.unwrap();
      let split: Vec<&str> = l.split_whitespace().collect();
      let expected = hex::decode(split[0]).expect("Error parse scalar");
      let plain = hex::decode(split[1]).expect("Error parse scalar");
      let actual = Hash::slow(&plain);
      assert!(actual == expected.as_slice());
    }
  }
}