From: Markus Triska Date: Tue, 12 May 2020 22:22:17 +0000 (+0200) Subject: ADDED: crypto_n_random_bytes/2, creating cryptographically secure random bytes X-Git-Tag: v0.8.123~36^2^2 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=716fde5784a1c0e2d4a9137c7e99d6ea18a7fb0c;p=scryer-prolog.git ADDED: crypto_n_random_bytes/2, creating cryptographically secure random bytes The ring crate is used since it will be needed also for future predicates in library(crypto). --- diff --git a/Cargo.toml b/Cargo.toml index 4db6b981..8e63ec9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,3 +34,4 @@ ref_thread_local = "0.0.0" rug = { version = "1.4.0", optional = true } rustyline = "6.0.0" unicode_reader = "1.0.0" +ring = "0.16.13" diff --git a/src/prolog/clause_types.rs b/src/prolog/clause_types.rs index 36f278df..0850735c 100644 --- a/src/prolog/clause_types.rs +++ b/src/prolog/clause_types.rs @@ -286,6 +286,7 @@ pub enum SystemClauseType { WriteTerm, WriteTermToChars, ScryerPrologVersion, + CryptoRandomByte } impl SystemClauseType { @@ -468,6 +469,7 @@ impl SystemClauseType { &SystemClauseType::WriteTerm => clause_name!("$write_term"), &SystemClauseType::WriteTermToChars => clause_name!("$write_term_to_chars"), &SystemClauseType::ScryerPrologVersion => clause_name!("$scryer_prolog_version"), + &SystemClauseType::CryptoRandomByte => clause_name!("$crypto_random_byte"), } } @@ -630,6 +632,7 @@ impl SystemClauseType { ("$write_term", 7) => Some(SystemClauseType::WriteTerm), ("$write_term_to_chars", 7) => Some(SystemClauseType::WriteTermToChars), ("$scryer_prolog_version", 1) => Some(SystemClauseType::ScryerPrologVersion), + ("$crypto_random_byte", 1) => Some(SystemClauseType::CryptoRandomByte), _ => None, } } diff --git a/src/prolog/lib/crypto.pl b/src/prolog/lib/crypto.pl index c91f7de1..36f68009 100644 --- a/src/prolog/lib/crypto.pl +++ b/src/prolog/lib/crypto.pl @@ -12,7 +12,8 @@ using strings leaves little trace of what was processed in the system, - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -:- module(crypto, [hex_bytes/2]). +:- module(crypto, [hex_bytes/2, + crypto_n_random_bytes/2]). :- use_module(library(error)). :- use_module(library(lists)). @@ -70,3 +71,10 @@ bytes_hex([B|Bs]) --> [C0,C1], char_hexval(C, H) :- nth0(H, "0123456789abcdef", C), !. char_hexval(C, H) :- nth0(H, "0123456789ABCDEF", C), !. + +crypto_n_random_bytes(N, Bs) :- + must_be(integer, N), + length(Bs, N), + maplist(crypto_random_byte, Bs). + +crypto_random_byte(B) :- '$crypto_random_byte'(B). diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 86f32fcb..343c62b1 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -38,6 +38,8 @@ use cpu_time::ProcessTime; use crate::crossterm::event::{read, Event, KeyCode, KeyEvent, KeyModifiers}; use crate::crossterm::terminal::{enable_raw_mode, disable_raw_mode}; +use ring::rand::{SecureRandom, SystemRandom}; + pub fn get_key() -> KeyEvent { let key; enable_raw_mode().expect("failed to enable raw mode"); @@ -5137,8 +5139,27 @@ impl MachineState { let result = Addr::HeapCell(self.heap.to_list(chars)); self.unify(version, result); } + &SystemClauseType::CryptoRandomByte => { + let arg = self[temp_v!(1)]; + let mut bytes: Vec = vec![0]; + rng().fill(&mut bytes); + + let byte = self.heap.put_constant(Constant::Integer(Rc::new(Integer::from(bytes[0])))); + self.unify(arg, byte); + } }; return_from_clause!(self.last_call, self) } } + + +fn rng() -> &'static SecureRandom { + use std::ops::Deref; + + lazy_static! { + static ref RANDOM: SystemRandom = SystemRandom::new(); + } + + RANDOM.deref() +}