]> Repositorios git - scryer-prolog.git/commitdiff
ADDED: Initial version of library(crypto).
authorMarkus Triska <[email protected]>
Fri, 8 May 2020 19:58:56 +0000 (21:58 +0200)
committerMarkus Triska <[email protected]>
Fri, 8 May 2020 20:33:49 +0000 (22:33 +0200)
src/prolog/lib/crypto.pl [new file with mode: 0644]

diff --git a/src/prolog/lib/crypto.pl b/src/prolog/lib/crypto.pl
new file mode 100644 (file)
index 0000000..c91f7de
--- /dev/null
@@ -0,0 +1,72 @@
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   Written May 2020 by Markus Triska ([email protected])
+   Part of Scryer Prolog.
+
+   Predicates for cryptographic applications.
+
+   This library assumes that the Prolog flag double_quotes is set to chars.
+   In Scryer Prolog, lists of characters are very efficiently represented,
+   and strings have the advantage that the atom table remains unmodified.
+
+   Especially for cryptographic applications, it as an advantage that
+   using strings leaves little trace of what was processed in the system,
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+:- module(crypto, [hex_bytes/2]).
+
+:- use_module(library(error)).
+:- use_module(library(lists)).
+:- use_module(library(between)).
+:- use_module(library(dcgs)).
+
+%   hex_bytes(?Hex, ?Bytes) is det.
+%
+%   Relation between a hexadecimal sequence and a list of bytes. Hex
+%   is a string of hexadecimal numbers. Bytes is a list of *integers*
+%   between 0 and 255 that represent the sequence as a list of bytes.
+%   At least one of the arguments must be instantiated.
+%
+%   Example:
+%
+%   ==
+%   ?- hex_bytes("501ACE", Bs).
+%      Bs = [80,26,206]
+%   ;  false.
+%   ==
+
+hex_bytes(Hs, Bytes) :-
+        (   ground(Hs) ->
+            must_be(list, Hs),
+            maplist(must_be(atom), Hs),
+            (   phrase(hex_bytes(Hs), Bytes) ->
+                true
+            ;   domain_error(hex_encoding, Hs, hex_bytes/2)
+            )
+        ;   must_be(list, Bytes),
+            maplist(must_be(integer), Bytes),
+            (   member(B, Bytes), \+ between(0, 255, B) ->
+                type_error(byte, B, hex_bytes/2)
+            ;   true
+            ),
+            phrase(bytes_hex(Bytes), Hs)
+        ).
+
+hex_bytes([]) --> [].
+hex_bytes([H1,H2|Hs]) --> [Byte],
+        { char_hexval(H1, High),
+          char_hexval(H2, Low),
+          Byte is High*16 + Low },
+        hex_bytes(Hs).
+
+bytes_hex([]) --> [].
+bytes_hex([B|Bs]) --> [C0,C1],
+        { High is B>>4,
+          Low is B /\ 0xf,
+          char_hexval(C0, High),
+          char_hexval(C1, Low)
+        },
+        bytes_hex(Bs).
+
+char_hexval(C, H) :- nth0(H, "0123456789abcdef", C), !.
+char_hexval(C, H) :- nth0(H, "0123456789ABCDEF", C), !.
+