ADDED: Hash-based message authentication code (HMAC), using hmac(Key).
This commit is contained in:
@@ -497,6 +497,8 @@ enum SystemClauseType {
|
|||||||
CryptoRandomByte,
|
CryptoRandomByte,
|
||||||
#[strum_discriminants(strum(props(Arity = "4", Name = "$crypto_data_hash")))]
|
#[strum_discriminants(strum(props(Arity = "4", Name = "$crypto_data_hash")))]
|
||||||
CryptoDataHash,
|
CryptoDataHash,
|
||||||
|
#[strum_discriminants(strum(props(Arity = "5", Name = "$crypto_hmac")))]
|
||||||
|
CryptoHMAC,
|
||||||
#[strum_discriminants(strum(props(Arity = "7", Name = "$crypto_data_hkdf")))]
|
#[strum_discriminants(strum(props(Arity = "7", Name = "$crypto_data_hkdf")))]
|
||||||
CryptoDataHKDF,
|
CryptoDataHKDF,
|
||||||
#[strum_discriminants(strum(props(Arity = "4", Name = "$crypto_password_hash")))]
|
#[strum_discriminants(strum(props(Arity = "4", Name = "$crypto_password_hash")))]
|
||||||
@@ -1846,6 +1848,7 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::CallScryerPrologVersion |
|
&Instruction::CallScryerPrologVersion |
|
||||||
&Instruction::CallCryptoRandomByte |
|
&Instruction::CallCryptoRandomByte |
|
||||||
&Instruction::CallCryptoDataHash |
|
&Instruction::CallCryptoDataHash |
|
||||||
|
&Instruction::CallCryptoHMAC |
|
||||||
&Instruction::CallCryptoDataHKDF |
|
&Instruction::CallCryptoDataHKDF |
|
||||||
&Instruction::CallCryptoPasswordHash |
|
&Instruction::CallCryptoPasswordHash |
|
||||||
&Instruction::CallCryptoCurveScalarMult |
|
&Instruction::CallCryptoCurveScalarMult |
|
||||||
@@ -2082,6 +2085,7 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::ExecuteScryerPrologVersion |
|
&Instruction::ExecuteScryerPrologVersion |
|
||||||
&Instruction::ExecuteCryptoRandomByte |
|
&Instruction::ExecuteCryptoRandomByte |
|
||||||
&Instruction::ExecuteCryptoDataHash |
|
&Instruction::ExecuteCryptoDataHash |
|
||||||
|
&Instruction::ExecuteCryptoHMAC |
|
||||||
&Instruction::ExecuteCryptoDataHKDF |
|
&Instruction::ExecuteCryptoDataHKDF |
|
||||||
&Instruction::ExecuteCryptoPasswordHash |
|
&Instruction::ExecuteCryptoPasswordHash |
|
||||||
&Instruction::ExecuteCryptoCurveScalarMult |
|
&Instruction::ExecuteCryptoCurveScalarMult |
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Written 2020-2023 by Markus Triska (triska@metalevel.at)
|
Written 2020-2024 by Markus Triska (triska@metalevel.at)
|
||||||
Part of Scryer Prolog.
|
Part of Scryer Prolog.
|
||||||
|
|
||||||
/** Predicates for cryptographic applications.
|
/** Predicates for cryptographic applications.
|
||||||
@@ -192,6 +192,11 @@ crypto_random_byte(B) :- '$crypto_random_byte'(B).
|
|||||||
% The default encoding is `utf8`. The alternative is `octet`, to
|
% The default encoding is `utf8`. The alternative is `octet`, to
|
||||||
% treat the input as a list of raw bytes.
|
% treat the input as a list of raw bytes.
|
||||||
%
|
%
|
||||||
|
% - `hmac(+Key)`
|
||||||
|
% Compute a hash-based message authentication code (HMAC) using
|
||||||
|
% Key, a list of bytes. This option is currently supported for
|
||||||
|
% algorithms `sha256`, `sha384` and `sha512`.
|
||||||
|
%
|
||||||
% Example:
|
% Example:
|
||||||
%
|
%
|
||||||
% ```
|
% ```
|
||||||
@@ -214,9 +219,18 @@ crypto_data_hash(Data0, Hash, Options0) :-
|
|||||||
( hash_algorithm(A) -> true
|
( hash_algorithm(A) -> true
|
||||||
; domain_error(hash_algorithm, A, crypto_data_hash/3)
|
; domain_error(hash_algorithm, A, crypto_data_hash/3)
|
||||||
),
|
),
|
||||||
'$crypto_data_hash'(Data, Encoding, HashBytes, A),
|
( member(HMAC, Options0), nonvar(HMAC), HMAC = hmac(Ks) ->
|
||||||
|
must_be_bytes(Ks, crypto_data_hash/3),
|
||||||
|
hmac_algorithm(A),
|
||||||
|
'$crypto_hmac'(Data, Encoding, Ks, HashBytes, A)
|
||||||
|
; '$crypto_data_hash'(Data, Encoding, HashBytes, A)
|
||||||
|
),
|
||||||
hex_bytes(Hash, HashBytes).
|
hex_bytes(Hash, HashBytes).
|
||||||
|
|
||||||
|
hmac_algorithm(sha256).
|
||||||
|
hmac_algorithm(sha384).
|
||||||
|
hmac_algorithm(sha512).
|
||||||
|
|
||||||
options_data_chars(Options, Data, Chars, Encoding) :-
|
options_data_chars(Options, Data, Chars, Encoding) :-
|
||||||
option(encoding(Encoding), Options, utf8),
|
option(encoding(Encoding), Options, utf8),
|
||||||
must_be(atom, Encoding),
|
must_be(atom, Encoding),
|
||||||
|
|||||||
@@ -4464,6 +4464,14 @@ impl Machine {
|
|||||||
self.crypto_data_hash();
|
self.crypto_data_hash();
|
||||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||||
}
|
}
|
||||||
|
&Instruction::CallCryptoHMAC => {
|
||||||
|
self.crypto_hmac();
|
||||||
|
step_or_fail!(self, self.machine_st.p += 1);
|
||||||
|
}
|
||||||
|
&Instruction::ExecuteCryptoHMAC => {
|
||||||
|
self.crypto_hmac();
|
||||||
|
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||||
|
}
|
||||||
&Instruction::CallCryptoDataHKDF => {
|
&Instruction::CallCryptoDataHKDF => {
|
||||||
self.crypto_data_hkdf();
|
self.crypto_data_hkdf();
|
||||||
step_or_fail!(self, self.machine_st.p += 1);
|
step_or_fail!(self, self.machine_st.p += 1);
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
|||||||
|
|
||||||
use blake2::{Blake2b, Blake2s};
|
use blake2::{Blake2b, Blake2s};
|
||||||
use ring::rand::{SecureRandom, SystemRandom};
|
use ring::rand::{SecureRandom, SystemRandom};
|
||||||
use ring::{digest, hkdf, pbkdf2};
|
use ring::{digest, hkdf, hmac, pbkdf2};
|
||||||
|
|
||||||
#[cfg(feature = "crypto-full")]
|
#[cfg(feature = "crypto-full")]
|
||||||
use ring::aead;
|
use ring::aead;
|
||||||
@@ -7393,6 +7393,40 @@ impl Machine {
|
|||||||
unify!(self.machine_st, self.machine_st.registers[3], ints_list);
|
unify!(self.machine_st, self.machine_st.registers[3], ints_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn crypto_hmac(&mut self) {
|
||||||
|
let encoding = cell_as_atom!(self.deref_register(2));
|
||||||
|
let data = self.string_encoding_bytes(self.machine_st.registers[1], encoding);
|
||||||
|
|
||||||
|
let stub_gen = || functor_stub(atom!("crypto_data_hash"), 3);
|
||||||
|
|
||||||
|
let key = self
|
||||||
|
.machine_st
|
||||||
|
.integers_to_bytevec(self.machine_st.registers[3], stub_gen);
|
||||||
|
|
||||||
|
let algorithm = cell_as_atom!(self.deref_register(5));
|
||||||
|
let ralg = match algorithm {
|
||||||
|
atom!("sha256") => hmac::HMAC_SHA256,
|
||||||
|
atom!("sha384") => hmac::HMAC_SHA384,
|
||||||
|
atom!("sha512") => hmac::HMAC_SHA512,
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let rkey = hmac::Key::new(ralg, key.as_ref());
|
||||||
|
let tag = hmac::sign(&rkey, &data);
|
||||||
|
|
||||||
|
let ints_list = heap_loc_as_cell!(iter_to_heap_list(
|
||||||
|
&mut self.machine_st.heap,
|
||||||
|
tag.as_ref()
|
||||||
|
.iter()
|
||||||
|
.map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
|
||||||
|
));
|
||||||
|
|
||||||
|
unify!(self.machine_st, self.machine_st.registers[4], ints_list);
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn crypto_data_hkdf(&mut self) {
|
pub(crate) fn crypto_data_hkdf(&mut self) {
|
||||||
let encoding = cell_as_atom!(self.deref_register(2));
|
let encoding = cell_as_atom!(self.deref_register(2));
|
||||||
|
|||||||
Reference in New Issue
Block a user