1/* Part of SWI-Prolog 2 3 Author: Matt Lilley and Markus Triska 4 WWW: http://www.swi-prolog.org 5 Copyright (c) 2004-2017, SWI-Prolog Foundation 6 VU University Amsterdam 7 All rights reserved. 8 9 Redistribution and use in source and binary forms, with or without 10 modification, are permitted provided that the following conditions 11 are met: 12 13 1. Redistributions of source code must retain the above copyright 14 notice, this list of conditions and the following disclaimer. 15 16 2. Redistributions in binary form must reproduce the above copyright 17 notice, this list of conditions and the following disclaimer in 18 the documentation and/or other materials provided with the 19 distribution. 20 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 POSSIBILITY OF SUCH DAMAGE. 33*/ 34 35:- module(crypto, 36 [ crypto_data_hash/3, % +Data, -Hash, +Options 37 crypto_file_hash/3, % +File, -Hash, +Options 38 crypto_context_new/2, % -Context, +Options 39 crypto_data_context/3, % +Data, +C0, -C 40 crypto_context_hash/2, % +Context, -Hash 41 crypto_open_hash_stream/3, % +InStream, -HashStream, +Options 42 crypto_stream_hash/2, % +HashStream, -Hash 43 ecdsa_sign/4, % +Key, +Data, -Signature, +Options 44 ecdsa_verify/4, % +Key, +Data, +Signature, +Options 45 evp_decrypt/6, % +CipherText, +Algorithm, +Key, +IV, -PlainText, +Options 46 evp_encrypt/6, % +PlainText, +Algorithm, +Key, +IV, -CipherText, +Options 47 hex_bytes/2, % ?Hex, ?List 48 rsa_private_decrypt/4, % +Key, +Ciphertext, -Plaintext, +Enc 49 rsa_private_encrypt/4, % +Key, +Plaintext, -Ciphertext, +Enc 50 rsa_public_decrypt/4, % +Key, +Ciphertext, -Plaintext, +Enc 51 rsa_public_encrypt/4, % +Key, +Plaintext, -Ciphertext, +Enc 52 rsa_sign/4, % +Key, +Data, -Signature, +Options 53 rsa_verify/4 % +Key, +Data, +Signature, +Options 54 ]). 55:- use_module(library(option)). 56 57:- use_foreign_library(foreign(crypto4pl)). 58 59 60/** <module> Cryptography and authentication library 61 62This library provides bindings to functionality of OpenSSL that is 63related to cryptography and authentication, not necessarily involving 64connections, sockets or streams. 65 66The hash functionality of this library subsumes and extends that of 67`library(sha)`, `library(hash_stream)` and `library(md5)` by providing a 68unified interface to all available digest algorithms. 69 70The underlying OpenSSL library (`libcrypto`) is dynamically loaded if 71_either_ `library(crypto)` or `library(ssl)` are loaded. Therefore, if 72your application uses `library(ssl)`, you can use `library(crypto)` for 73hashing without increasing the memory footprint of your application. In 74other cases, the specialised hashing libraries are more lightweight but 75less general alternatives to `library(crypto)`. 76 77@author Matt Lilley 78@author [Markus Triska](https://www.metalevel.at) 79*/ 80 81%% crypto_data_hash(+Data, -Hash, +Options) is det 82% 83% Hash is the hash of Data. The conversion is controlled 84% by Options: 85% 86% * algorithm(+Algorithm) 87% One of =md5=, =sha1=, =sha224=, =sha256= (default), =sha384=, 88% =sha512=, =blake2s256= or =blake2b512=. The =BLAKE= digest 89% algorithms require OpenSSL 1.1.0 or greater. 90% * encoding(+Encoding) 91% If Data is a sequence of character _codes_, this must be 92% translated into a sequence of _bytes_, because that is what 93% the hashing requires. The default encoding is =utf8=. The 94% other meaningful value is =octet=, claiming that Data contains 95% raw bytes. 96% * hmac(+Key) 97% If this option is specified, a _hash-based message authentication 98% code_ (HMAC) is computed, using the specified Key which is either 99% an atom or string. Any of the available digest algorithms can be 100% used with this option. The cryptographic strength of the HMAC 101% depends on that of the chosen algorithm and also on the key. This 102% option requires OpenSSL 1.1.0 or greater. 103% 104% @param Data is either an atom, string or code-list 105% @param Hash is an atom that represents the hash. 106% 107% @see hex_bytes/2 for conversion between hashes and lists. 108 109crypto_data_hash(Data, Hash, Options) :- 110 crypto_context_new(Context0, Options), 111 crypto_data_context(Data, Context0, Context), 112 crypto_context_hash(Context, Hash). 113 114%! crypto_file_hash(+File, -Hash, +Options) is det. 115% 116% True if Hash is the hash of the content of File. For Options, 117% see crypto_data_hash/3. 118 119crypto_file_hash(File, Hash, Options) :- 120 setup_call_cleanup(open(File, read, In, [type(binary)]), 121 crypto_stream_hash(In, Hash, Options), 122 close(In)). 123 124crypto_stream_hash(Stream, Hash, Options) :- 125 crypto_context_new(Context0, Options), 126 update_hash(Stream, Context0, Context), 127 crypto_context_hash(Context, Hash). 128 129update_hash(In, Context0, Context) :- 130 ( at_end_of_stream(In) 131 -> Context = Context0 132 ; read_pending_codes(In, Data, []), 133 crypto_data_context(Data, Context0, Context1), 134 update_hash(In, Context1, Context) 135 ). 136 137 138%! crypto_context_new(-Context, +Options) is det. 139% 140% Context is unified with the empty context, taking into account 141% Options. The context can be used in crypto_data_context/3. For 142% Options, see crypto_data_hash/3. 143% 144% @param Context is an opaque pure Prolog term that is subject to 145% garbage collection. 146 147%! crypto_data_context(+Data, +Context0, -Context) is det 148% 149% Context0 is an existing computation context, and Context is the 150% new context after hashing Data in addition to the previously 151% hashed data. Context0 may be produced by a prior invocation of 152% either crypto_context_new/2 or crypto_data_context/3 itself. 153% 154% This predicate allows a hash to be computed in chunks, which may 155% be important while working with Metalink (RFC 5854), BitTorrent 156% or similar technologies, or simply with big files. 157 158crypto_data_context(Data, Context0, Context) :- 159 '_crypto_context_copy'(Context0, Context), 160 '_crypto_update_context'(Data, Context). 161 162 163%! crypto_context_hash(+Context, -Hash) 164% 165% Obtain the hash code of Context. Hash is an atom representing 166% the hash code that is associated with the current state of the 167% computation context Context. 168 169crypto_context_hash(Context, Hash) :- 170 '_crypto_context_copy'(Context, Copy), 171 '_crypto_context_hash'(Copy, List), 172 hex_bytes(Hash, List). 173 174%! crypto_open_hash_stream(+OrgStream, -HashStream, +Options) is det. 175% 176% Open a filter stream on OrgStream that maintains a hash. The hash 177% can be retrieved at any time using crypto_stream_hash/2. Available 178% Options in addition to those of crypto_data_hash/3 are: 179% 180% - close_parent(+Bool) 181% If `true` (default), closing the filter stream also closes the 182% original (parent) stream. 183 184crypto_open_hash_stream(OrgStream, HashStream, Options) :- 185 crypto_context_new(Context, Options), 186 '_crypto_open_hash_stream'(OrgStream, HashStream, Context). 187 188 189%! crypto_stream_hash(+HashStream, -Hash) is det. 190% 191% Unify Hash with a hash for the bytes sent to or read from 192% HashStream. Note that the hash is computed on the stream 193% buffers. If the stream is an output stream, it is first flushed 194% and the Digest represents the hash at the current location. If 195% the stream is an input stream the Digest represents the hash of 196% the processed input including the already buffered data. 197 198crypto_stream_hash(Stream, Hash) :- 199 '_crypto_stream_context'(Stream, Context), 200 crypto_context_hash(Context, Hash). 201 202%! ecdsa_sign(+Key, +Data, -Signature, +Options) 203% 204% Create an ECDSA signature for Data with EC private key Key. 205% Among the most common cases is signing a hash that was created 206% with crypto_data_hash/3 or other predicates of this library. For 207% this reason, the default encoding (`hex`) assumes that Data is 208% an atom, string, character list or code list representing the 209% data in hexadecimal notation. See rsa_sign/4 for an example. 210% 211% Options: 212% 213% - encoding(+Encoding) 214% Encoding to use for Data. Default is `hex`. Alternatives 215% are `octet`, `utf8` and `text`. 216 217ecdsa_sign(private_key(ec(Private,Public0,Curve)), Data0, Signature, Options) :- 218 option(encoding(Enc0), Options, hex), 219 hex_encoding(Enc0, Data0, Enc, Data), 220 hex_bytes(Public0, Public), 221 '_crypto_ecdsa_sign'(ec(Private,Public,Curve), Data, Enc, Signature). 222 223hex_encoding(hex, Data0, octet, Data) :- !, 224 hex_bytes(Data0, Data). 225hex_encoding(Enc, Data, Enc, Data). 226 227%! ecdsa_verify(+Key, +Data, +Signature, +Options) is semidet. 228% 229% True iff Signature can be verified as the ECDSA signature for 230% Data, using the EC public key Key. 231% 232% Options: 233% 234% - encoding(+Encoding) 235% Encoding to use for Data. Default is `hex`. Alternatives 236% are `octet`, `utf8` and `text`. 237 238ecdsa_verify(public_key(ec(Private,Public0,Curve)), Data0, Signature0, Options) :- 239 option(encoding(Enc0), Options, hex), 240 hex_encoding(Enc0, Data0, Enc, Data), 241 hex_bytes(Public0, Public), 242 hex_bytes(Signature0, Signature), 243 '_crypto_ecdsa_verify'(ec(Private,Public,Curve), Data, Enc, Signature). 244 245 246%! hex_bytes(?Hex, ?List) is det. 247% 248% Relation between a hexadecimal sequence and a list of bytes. Hex 249% is an atom, string, list of characters or list of codes in 250% hexadecimal encoding. This is the format that is used by 251% crypto_data_hash/3 and related predicates to represent _hashes_. 252% Bytes is a list of _integers_ between 0 and 255 that represent the 253% sequence as a list of bytes. At least one of the arguments must 254% be instantiated. When converting List _to_ Hex, an _atom_ is used 255% to represent the sequence of hexadecimal digits. 256% 257% Example: 258% 259% == 260% ?- hex_bytes('501ACE', Bs). 261% Bs = [80, 26, 206]. 262% == 263 264hex_bytes(Hs, Bytes) :- 265 ( ground(Hs) -> 266 string_chars(Hs, Chars), 267 ( phrase(hex_bytes(Chars), Bytes) 268 -> true 269 ; domain_error(hex_encoding, Hs) 270 ) 271 ; must_be(list(between(0,255)), Bytes), 272 phrase(bytes_hex(Bytes), Chars), 273 atom_chars(Hs, Chars) 274 ). 275 276hex_bytes([]) --> []. 277hex_bytes([H1,H2|Hs]) --> [Byte], 278 { char_type(H1, xdigit(High)), 279 char_type(H2, xdigit(Low)), 280 Byte is High*16 + Low }, 281 hex_bytes(Hs). 282 283bytes_hex([]) --> []. 284bytes_hex([B|Bs]) --> 285 { High is B>>4, 286 Low is B /\ 0xf, 287 char_type(C0, xdigit(High)), 288 char_type(C1, xdigit(Low)) 289 }, 290 [C0,C1], 291 bytes_hex(Bs). 292 293%! rsa_private_decrypt(+PrivateKey, +CipherText, -PlainText, +Options) is det. 294%! rsa_private_encrypt(+PrivateKey, +PlainText, -CipherText, +Options) is det. 295%! rsa_public_decrypt(+PublicKey, +CipherText, -PlainText, +Options) is det. 296%! rsa_public_encrypt(+PublicKey, +PlainText, -CipherText, +Options) is det. 297% 298% RSA Public key encryption and decryption primitives. A string 299% can be safely communicated by first encrypting it and have the 300% peer decrypt it with the matching key and predicate. The length 301% of the string is limited by the key length. 302% 303% Options: 304% 305% - encoding(+Encoding) 306% Encoding to use for Data. Default is `utf8`. Alternatives 307% are `utf8` and `octet`. 308% 309% - padding(+PaddingScheme) 310% Padding scheme to use. Default is `pkcs1`. Alternatives 311% are `pkcs1_oaep`, `sslv23` and `none`. Note that `none` should 312% only be used if you implement cryptographically sound padding 313% modes in your application code as encrypting unpadded data with 314% RSA is insecure 315% 316% @see load_private_key/3, load_public_key/2 can be use to load 317% keys from a file. The predicate load_certificate/2 can be used 318% to obtain the public key from a certificate. 319% 320% @error ssl_error(Code, LibName, FuncName, Reason) is raised if 321% there is an error, e.g., if the text is too long for the key. 322 323%! rsa_sign(+Key, +Data, -Signature, +Options) is det. 324% 325% Create an RSA signature for Data with private key Key. Options: 326% 327% - type(+Type) 328% SHA algorithm used to compute the digest. Values are 329% `sha1` (default), `sha224`, `sha256`, `sha384` or `sha512`. 330% 331% - encoding(+Encoding) 332% Encoding to use for Data. Default is `hex`. Alternatives 333% are `octet`, `utf8` and `text`. 334% 335% This predicate can be used to compute a =|sha256WithRSAEncryption|= 336% signature as follows: 337% 338% ``` 339% sha256_with_rsa(PemKeyFile, Password, Data, Signature) :- 340% Algorithm = sha256, 341% read_key(PemKeyFile, Password, Key), 342% crypto_data_hash(Data, Hash, [algorithm(Algorithm), 343% encoding(octet)]), 344% rsa_sign(Key, Hash, Signature, [type(Algorithm)]). 345% 346% read_key(File, Password, Key) :- 347% setup_call_cleanup( 348% open(File, read, In, [type(binary)]), 349% load_private_key(In, Password, Key), 350% close(In)). 351% ``` 352% 353% Note that a hash that is computed by crypto_data_hash/3 can be 354% directly used in rsa_sign/4 as well as ecdsa_sign/4. 355 356rsa_sign(Key, Data0, Signature, Options) :- 357 option(type(Type), Options, sha1), 358 option(encoding(Enc0), Options, hex), 359 hex_encoding(Enc0, Data0, Enc, Data), 360 rsa_sign(Key, Type, Enc, Data, Signature). 361 362 363%! rsa_verify(+Key, +Data, +Signature, +Options) is semidet. 364% 365% Verify an RSA signature for Data with public key Key. 366% 367% Options: 368% 369% - type(+Type) 370% SHA algorithm used to compute the digest. Values are 371% `sha1` (default), `sha224`, `sha256`, `sha384` or `sha512`. 372% 373% - encoding(+Encoding) 374% Encoding to use for Data. Default is `hex`. Alternatives 375% are `octet`, `utf8` and `text`. 376 377rsa_verify(Key, Data0, Signature0, Options) :- 378 option(type(Type), Options, sha1), 379 option(encoding(Enc0), Options, hex), 380 hex_encoding(Enc0, Data0, Enc, Data), 381 hex_bytes(Signature0, Signature), 382 rsa_verify(Key, Type, Enc, Data, Signature). 383 384%! evp_decrypt(+CipherText, 385%! +Algorithm, 386%! +Key, 387%! +IV, 388%! -PlainText, 389%! +Options). 390% 391% Decrypt the given CipherText, using the symmetric algorithm 392% Algorithm, key Key, and iv IV, to give PlainText. CipherText, Key 393% and IV should all be strings, and PlainText is created as a string 394% as well. Algorithm should be an algorithm which your copy of OpenSSL 395% knows about. Examples are: 396% 397% * aes-128-cbc 398% * aes-256-cbc 399% * des3 400% 401% If the IV is not needed for your decryption algorithm (such as 402% aes-128-ecb) then any string can be provided as it will be ignored 403% by the underlying implementation 404% 405% Options: 406% 407% - encoding(+Encoding) 408% Encoding to use for Data. Default is `utf8`. Alternatives 409% are `utf8` and `octet`. 410% 411% - padding(+PaddingScheme) 412% Padding scheme to use. Default is `block`. You can disable padding 413% by supplying 414% `none` here. 415% 416% Example of aes-128-cbc encryption: 417% 418% ``` 419% ?- evp_encrypt("this is some input", 'aes-128-cbc', "sixteenbyteofkey", 420% "sixteenbytesofiv", CipherText, []), 421% evp_decrypt(CipherText, 'aes-128-cbc', 422% "sixteenbyteofkey", "sixteenbytesofiv", 423% RecoveredText, []). 424% CipherText = <binary string> 425% RecoveredText = "this is some input". 426% ``` 427 428%! evp_encrypt(+PlainText, 429%! +Algorithm, 430%! +Key, 431%! +IV, 432%! -CipherTExt, 433%! +Options). 434% 435% Encrypt the given PlainText, using the symmetric algorithm 436% Algorithm, key Key, and iv IV, to give CipherText. See 437% evp_decrypt/6. 438 439 /******************************* 440 * Sandboxing * 441 *******************************/ 442 443:- multifile sandbox:safe_primitive/1. 444 445sandbox:safe_primitive(crypto:crypto_data_hash(_,_,_)). 446sandbox:safe_primitive(crypto:crypto_data_context(_,_,_)). 447sandbox:safe_primitive(crypto:crypto_context_new(_,_)). 448sandbox:safe_primitive(crypto:crypto_context_hash(_,_)). 449 450 /******************************* 451 * MESSAGES * 452 *******************************/ 453 454:- multifile 455 prolog:error_message//1. 456 457prologerror_message(ssl_error(ID, _Library, Function, Reason)) --> 458 [ 'SSL(~w) ~w: ~w'-[ID, Function, Reason] ].