cryptonote-raw-crypto 0.5.1

Cryptography Primitives for Cryptonote
Documentation
extern "C" {
  fn check_scalar(scalar: *const u8) -> bool;
  fn random_scalar(secret_key: *mut u8);
  fn hash_to_scalar(data: *const u8, length: usize, hash: *mut u8);
  fn hash_to_point(hash: *const u8, point: *mut u8);
  fn hash_to_ec_ex(hash: *const u8, ec: *mut u8);
}

pub struct EllipticCurveScalar {}

pub struct EllipticCurvePoint {}

impl EllipticCurveScalar {
  pub fn check(scalar: &[u8; 32]) -> bool {
    unsafe { return check_scalar(scalar[..].as_ptr()) }
  }

  pub fn random(secret_key: &mut [u8; 32]) {
    unsafe {
      random_scalar(secret_key.as_mut_ptr());
    }
  }
  pub fn to_hash(scalar: &[u8]) -> [u8; 32] {
    let mut hash: [u8; 32] = [0; 32];
    unsafe { hash_to_scalar(scalar.as_ptr(), scalar.len(), hash.as_mut_ptr()) }
    hash
  }

  pub fn from_hash(hash: &[u8]) -> [u8; 32] {
    let mut ec: [u8; 32] = [0; 32];
    unsafe { hash_to_ec_ex(hash.as_ptr(), ec.as_mut_ptr()) }
    ec
  }
}

impl EllipticCurvePoint {
  pub fn from_hash(hash: &[u8]) -> [u8; 32] {
    let mut point: [u8; 32] = [0; 32];
    unsafe {
      hash_to_point(hash.as_ptr(), point.as_mut_ptr());
    }
    point
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use std::fs::{canonicalize, File};
  use std::io::{prelude::*, BufReader};
  use std::path::PathBuf;
  extern crate hex;
  use super::super::key::Key;
  use super::super::ring::Ring;

  extern "C" {
    fn setup_random(value: i32);
  }

  fn to_fixed_32(variant: Vec<u8>) -> [u8; 32] {
    let mut fixed: [u8; 32] = [0; 32];
    for i in 0..32 {
      fixed[i] = variant[i];
    }
    fixed
  }

  fn to_fixed_64(variant: Vec<u8>) -> [u8; 64] {
    let mut fixed: [u8; 64] = [0; 64];
    for i in 0..64 {
      fixed[i] = variant[i];
    }
    fixed
  }

  #[test]
  fn should_to_hash() {
    let bytes = hex::decode("2ace").expect("Error parse scalar");
    let hash = EllipticCurveScalar::to_hash(bytes.as_slice());
    let expected = hex::decode("427f5090283713a2a8448285f2a22cc8cf5374845766b6370425e2319e40f50d")
      .expect("Error parse scalar");
    assert!(hash == expected.as_slice());
  }

  #[test]
  fn should_test_scalar() {
    let path = PathBuf::from("./tests/tests.txt");
    let str = canonicalize(path);
    let f = File::open(str.unwrap()).unwrap();
    let file = BufReader::new(&f);
    let mut last = String::from("");
    let mut executed = false;
    for (_num, line) in file.lines().enumerate() {
      let l = line.unwrap();
      let split: Vec<&str> = l.split_whitespace().collect();
      let name = split[0];
      if last != name {
        last = split[0].to_string();
      }
      match name {
        "check_scalar" => {
          let plain = hex::decode(split[1]).expect("Error parse scalar");
          let expected = split[2] == String::from("true");
          let mut scalar: [u8; 32] = [0; 32];
          for i in 0..32 {
            scalar[i] = plain[i];
          }
          let actual = EllipticCurveScalar::check(&scalar);
          assert!(expected == actual)
        }
        "random_scalar" => {
          if !executed {
            unsafe {
              setup_random(42);
            }
            executed = true;
          }
          let expected = hex::decode(split[1]).expect("Error parse expected");
          let mut ec_scalar: [u8; 32] = [0; 32];
          EllipticCurveScalar::random(&mut ec_scalar);
          for i in 0..32 {
            assert!(expected[i] == ec_scalar[i]);
          }
        }
        "hash_to_scalar" => {
          let bytes: Vec<u8>;
          if split[1] == "x" {
            bytes = hex::decode("").expect("Error parse scalar");
          } else {
            bytes = hex::decode(split[1]).expect("Error parse scalar");
          }
          let hash = EllipticCurveScalar::to_hash(bytes.as_slice());
          let expected = hex::decode(split[2]).expect("Error parse expected");
          assert!(hash == expected.as_slice());
        }
        "generate_keys" => {
          let public_key = hex::decode(split[1]).expect("Error parse expected");
          let private_key = hex::decode(split[2]).expect("Error parse expected");
          let mut generated_public_key: [u8; 32] = [0; 32];
          let mut generated_private_key: [u8; 32] = [0; 32];
          Key::generate_key_pair(&mut generated_public_key, &mut generated_private_key);
          assert!(to_fixed_32(public_key) == generated_public_key);
          assert!(to_fixed_32(private_key) == generated_private_key);
        }
        "check_key" => {
          let public_key = hex::decode(split[1]).expect("Error parse expected");
          assert!(public_key.len() == 32);
          let expected = split[2] == "true";
          assert!(Key::check_public_key(&to_fixed_32(public_key)) == expected);
        }
        "secret_key_to_public_key" => {
          let secret_key = hex::decode(split[1]).expect("Error parse expected");
          let expected1 = split[2] == "true";
          let mut public_key: [u8; 32] = [0; 32];
          let actual1 = Key::secret_to_public(&to_fixed_32(secret_key), &mut public_key);
          assert!(expected1 == actual1);
          if expected1 == true {
            let expected2 = hex::decode(split[3]).expect("Error parse expected");
            assert!(public_key == expected2.as_slice());
          }
        }
        "generate_key_derivation" => {
          let public_key = hex::decode(split[1]).expect("Error parse expected");
          let secret_key = hex::decode(split[2]).expect("Error parse expected");
          let expected1 = split[3] == "true";
          let derived = Key::generate_key_derivation(&to_fixed_32(public_key), &to_fixed_32(secret_key));
          if expected1 {
            let expected2 = hex::decode(split[4]).expect("Error parse expected");
            assert!(derived == expected2.as_slice());
          } else {
            assert!(derived == [0; 32]);
          }
        }
        "derive_public_key" => {
          let derivation = hex::decode(split[1]).expect("Error parse derivation");
          let out_index = split[2].parse::<u32>().unwrap();
          let public_key = hex::decode(split[3]).expect("Error parse public key");
          let expected1 = split[4] == "true";
          let derived = Key::derive_public_key(&to_fixed_32(derivation), out_index as u64, &to_fixed_32(public_key));

          if expected1 {
            let expected2 = hex::decode(split[5]).expect("Error parse expected derived");
            assert!(expected2.as_slice() == derived);
          } else {
            assert!(derived == [0; 32]);
          }
        }
        "derive_secret_key" => {
          let derivation = hex::decode(split[1]).expect("Error parse derivation");
          let out_index = split[2].parse::<u32>().unwrap();

          let private_key = hex::decode(split[3]).expect("Error parse public key");
          let expected = hex::decode(split[4]).expect("Error parse public key");
          let derived = Key::derive_secret_key(&to_fixed_32(derivation), out_index as u64, &to_fixed_32(private_key));
          assert!(derived == expected.as_slice());
        }
        "underive_public_key" => {
          let derivation = hex::decode(split[1]).expect("Error parse derivation");
          let out_index = split[2].parse::<u32>().unwrap();
          let public_key = hex::decode(split[3]).expect("Error parse public key");
          let expected1 = split[4] == "true";
          let derived = Key::underive_public_key(&to_fixed_32(derivation), out_index as u64, &to_fixed_32(public_key));

          if expected1 {
            let expected2 = hex::decode(split[5]).expect("Error parse expected derived");
            assert!(expected2.as_slice() == derived);
          } else {
            assert!(derived == [0; 32]);
          }
        }
        "generate_signature" => {
          let prefix_hash = hex::decode(split[1]).expect("Error parse prefix hash");
          let public_key = hex::decode(split[2]).expect("Error parse public key");
          let secret_key = hex::decode(split[3]).expect("Error parse secret key");
          let expected = hex::decode(split[4]).expect("Error parse expected signature");

          let actual = Key::generate_signature(
            &to_fixed_32(prefix_hash),
            &to_fixed_32(public_key),
            &to_fixed_32(secret_key),
          );
          for i in 0..64 {
            assert!(expected[i] == actual[i]);
          }
        }
        "check_signature" => {
          let prefix_hash = hex::decode(split[1]).expect("Error parse prefix hash");
          let public_key = hex::decode(split[2]).expect("Error parse public key");
          let signature = hex::decode(split[3]).expect("Error parse secret key");
          let expected = split[4] == "true";

          let actual = Key::check_signature(
            &to_fixed_32(prefix_hash),
            &to_fixed_32(public_key),
            &to_fixed_64(signature),
          );
          assert!(expected == actual);
        }
        "hash_to_point" => {
          let hash = hex::decode(split[1]).expect("Error parse prefix hash");
          let expected = hex::decode(split[2]).expect("Error parse public key");
          let actual = EllipticCurvePoint::from_hash(hash.as_slice());
          assert!(expected == actual);
        }
        "hash_to_ec" => {
          let public_key = hex::decode(split[1]).expect("Error parse prefix hash");
          let expected = hex::decode(split[2]).expect("Error parse public key");
          let actual = EllipticCurveScalar::from_hash(public_key.as_slice());
          assert!(expected == actual);
        }
        "generate_key_image" => {
          let public_key = hex::decode(split[1]).expect("Error parse prefix hash");
          let secret_key = hex::decode(split[2]).expect("Error parse public key");
          let expected = hex::decode(split[3]).expect("Error parse public key");
          let actual = Key::generate_key_image(&to_fixed_32(public_key), &to_fixed_32(secret_key));
          assert!(expected == actual);
        }
        "generate_ring_signature" => {
          let prefix_hash = hex::decode(split[1]).expect("Error parse prefix hash");
          let image = hex::decode(split[2]).expect("Error parse key image");
          let pubs_count = split[3].parse::<usize>().unwrap();

          let mut pubsv: Vec<[u8; 32]> = vec![];
          for i in 0..pubs_count {
            let public_key = hex::decode(split[(4 + i)]).expect("Error parse public key");
            let fixed = to_fixed_32(public_key);
            pubsv.push(fixed);
          }
          let secret_key = hex::decode(split[(4 + pubs_count)]).expect("Error parse secret key");
          let secret_index = split[(5 + pubs_count)].parse::<usize>().unwrap();
          let expected = hex::decode(split[(6 + pubs_count)]).expect("Error parse signatures");
          let actual = Ring::generate_signature(
            &to_fixed_32(prefix_hash),
            &to_fixed_32(image),
            &pubsv,
            pubs_count,
            &to_fixed_32(secret_key),
            secret_index,
          );
          assert!(expected == actual);
        }
        "check_ring_signature" => {
          let prefix_hash = hex::decode(split[1]).expect("Error parse prefix hash");
          let image = hex::decode(split[2]).expect("Error parse key image");
          let pubs_count = split[3].parse::<usize>().unwrap();

          let mut pubsv: Vec<[u8; 32]> = vec![];
          for i in 0..pubs_count {
            let public_key = hex::decode(split[(4 + i)]).expect("Error parse public key");
            let fixed = to_fixed_32(public_key);
            pubsv.push(fixed);
          }
          let signatures = hex::decode(split[(4 + pubs_count)]).expect("Error parse secret key");
          let expected = split[(5 + pubs_count)] == "true";
          let actual = Ring::check_signature(
            &to_fixed_32(prefix_hash),
            &to_fixed_32(image),
            &pubsv,
            pubs_count,
            &signatures
          );
          assert!(expected == actual);
        }
        _ => {}
      }
    }
  }
}