diff --git a/Cargo.toml b/Cargo.toml index 3f48283c..b869277c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,3 +36,5 @@ rustyline = "6.0.0" unicode_reader = "1.0.0" ring = "0.16.13" ripemd160 = "0.8.0" +sha3 = "0.8.2" +blake2 = "0.8.1" diff --git a/src/prolog/lib/crypto.pl b/src/prolog/lib/crypto.pl index 909127d4..e07b4b1d 100644 --- a/src/prolog/lib/crypto.pl +++ b/src/prolog/lib/crypto.pl @@ -158,11 +158,11 @@ crypto_random_byte(B) :- '$crypto_random_byte'(B). Options is a list of: - algorithm(+A) - where A is one of ripemd160, sha256, sha384, sha512, - sha512_256, or a variable. If A is a variable, then it is - unified with the default algorithm, which is an algorithm that - is considered cryptographically secure at the time of this - writing. + where A is one of ripemd160, sha256, sha384, sha512, sha512_256, + sha3_224, sha3_256, sha3_384, sha3_512, blake2s256, blake2b512, + or a variable. If A is a variable, then it is unified with the + default algorithm, which is an algorithm that is considered + cryptographically secure at the time of this writing. - encoding(+Encoding) The default encoding is utf8. The alternative is octet, to treat the input as a list of raw bytes. @@ -215,6 +215,12 @@ hash_algorithm(sha256). hash_algorithm(sha512). hash_algorithm(sha384). hash_algorithm(sha512_256). +hash_algorithm(sha3_224). +hash_algorithm(sha3_256). +hash_algorithm(sha3_384). +hash_algorithm(sha3_512). +hash_algorithm(blake2s256). +hash_algorithm(blake2b512). /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -230,10 +236,9 @@ hash_algorithm(sha512_256). Admissible options are: - algorithm(+Algorithm) - A hashing algorithm as specified to crypto_data_hash/3. The - default is a cryptographically secure algorithm. If you - specify a variable, then it is unified with the algorithm - that was used, which is a cryptographically secure algorithm. + One of sha256, sha384 or sha512. If you specify a variable, + then it is unified with the algorithm that was used, which is a + cryptographically secure algorithm by default. - info(+Info) Optional context and application specific information, specified as a list of bytes or characters. The default is []. @@ -253,6 +258,9 @@ hash_algorithm(sha512_256). crypto_data_hkdf(Data0, L, Bytes, Options0) :- functor_hash_options(algorithm, Algorithm, Options0, Options), + ( hkdf_algorithm(Algorithm) -> true + ; domain_error(hkdf_algorithm, Algorithm, crypto_data_hkdf/4) + ), must_be(integer, L), L >= 0, options_data_bytes(Options, Data0, Data), @@ -262,6 +270,10 @@ crypto_data_hkdf(Data0, L, Bytes, Options0) :- chars_bytes_(Info0, Info, crypto_data_hkdf/4), '$crypto_data_hkdf'(Data, SaltBytes, Info, Algorithm, L, Bytes). +hkdf_algorithm(sha256). +hkdf_algorithm(sha384). +hkdf_algorithm(sha512). + option(What, Options, Default) :- ( member(V, Options), var(V) -> instantiation_error(option/3) @@ -587,7 +599,9 @@ crypto_data_decrypt(CipherText0, Algorithm, Key, IV, PlainText, Options) :- must_be_bytes(Key, crypto_data_decrypt/6), must_be_bytes(IV, crypto_data_decrypt/6), must_be(atom, Algorithm), - encoding_options(Encoding, Options), + option(encoding(Encoding), Options, utf8), + must_be(atom, Encoding), + member(Encoding, [utf8,octet]), must_be(list, CipherText0), encoding_bytes(octet, CipherText0, CipherText1), append(CipherText1, Tag, CipherText), diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 927fa028..4eacea2a 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -42,6 +42,8 @@ use crate::crossterm::terminal::{enable_raw_mode, disable_raw_mode}; use ring::rand::{SecureRandom, SystemRandom}; use ring::{digest,hkdf,pbkdf2,aead,error}; use ripemd160::{Ripemd160, Digest}; +use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512}; +use blake2::{Blake2s, Blake2b}; pub fn get_key() -> KeyEvent { let key; @@ -5241,21 +5243,39 @@ impl MachineState { }; let ints_list = - if algorithm_str == "ripemd160" { - let mut context = Ripemd160::new(); - context.input(&bytes); - Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::Integer(Rc::new(Integer::from(*b)))))) - } else { - let ints = digest::digest( - match algorithm_str { - "sha256" => { &digest::SHA256 } - "sha384" => { &digest::SHA384 } - "sha512" => { &digest::SHA512 } - "sha512_256" => { &digest::SHA512_256 } - _ => { unreachable!() } - }, - &bytes); - Addr::HeapCell(self.heap.to_list(ints.as_ref().iter().map(|b| HeapCellValue::Integer(Rc::new(Integer::from(*b)))))) + match algorithm_str { + "sha3_224" => { let mut context = Sha3_224::new(); + context.input(&bytes); + Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) } + "sha3_256" => { let mut context = Sha3_256::new(); + context.input(&bytes); + Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) } + "sha3_384" => { let mut context = Sha3_384::new(); + context.input(&bytes); + Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) } + "sha3_512" => { let mut context = Sha3_512::new(); + context.input(&bytes); + Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) } + "blake2s256" => { let mut context = Blake2s::new(); + context.input(&bytes); + Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) } + "blake2b512" => { let mut context = Blake2b::new(); + context.input(&bytes); + Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) } + "ripemd160" => { let mut context = Ripemd160::new(); + context.input(&bytes); + Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) } + _ => { let ints = digest::digest( + match algorithm_str { + "sha256" => { &digest::SHA256 } + "sha384" => { &digest::SHA384 } + "sha512" => { &digest::SHA512 } + "sha512_256" => { &digest::SHA512_256 } + _ => { unreachable!() } + }, + &bytes); + Addr::HeapCell(self.heap.to_list(ints.as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) + } }; self.unify(self[temp_v!(2)], ints_list); @@ -5287,11 +5307,12 @@ impl MachineState { usize::try_from(n).unwrap() } Ok(Number::Integer(n)) => { - n.to_usize().unwrap() - } - _ => { - unreachable!() + match n.to_usize() { + Some(u) => { u } + _ => { self.fail = true; return Ok(()); } + } } + _ => { unreachable!() } }; let ints_list = @@ -5300,7 +5321,7 @@ impl MachineState { "sha256" => { hkdf::HKDF_SHA256 } "sha384" => { hkdf::HKDF_SHA384 } "sha512" => { hkdf::HKDF_SHA512 } - _ => { unreachable!() } + _ => { self.fail = true; return Ok(()); } }; let salt = hkdf::Salt::new(digest_alg, &salt); let mut bytes : Vec = Vec::new(); @@ -5310,7 +5331,7 @@ impl MachineState { _ => { self.fail = true; return Ok(()); } } - Addr::HeapCell(self.heap.to_list(bytes.iter().map(|b| HeapCellValue::Integer(Rc::new(Integer::from(*b)))))) + Addr::HeapCell(self.heap.to_list(bytes.iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) }; self.unify(self[temp_v!(6)], ints_list); @@ -5343,7 +5364,7 @@ impl MachineState { NonZeroU32::new(iterations as u32).unwrap(), &salt, &data, &mut bytes); - Addr::HeapCell(self.heap.to_list(bytes.iter().map(|b| HeapCellValue::Integer(Rc::new(Integer::from(*b)))))) + Addr::HeapCell(self.heap.to_list(bytes.iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) }; self.unify(self[temp_v!(4)], ints_list); @@ -5368,7 +5389,7 @@ impl MachineState { }; let tag_list = - Addr::HeapCell(self.heap.to_list(tag.as_ref().iter().map(|b| HeapCellValue::Integer(Rc::new(Integer::from(*b)))))); + Addr::HeapCell(self.heap.to_list(tag.as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))); let complete_string = { let buffer = String::from_iter(in_out.iter().map(|b| *b as char));