• Places
    • Home
    • Graphs
    • Prefixes
  • Admin
    • Users
    • Settings
    • Plugins
    • Statistics
  • Repository
    • Load local file
    • Load from HTTP
    • Load from library
    • Remove triples
    • Clear repository
  • Query
    • YASGUI SPARQL Editor
    • Simple Form
  • Help
    • Documentation
    • Tutorial
    • Roadmap
    • HTTP Services
  • Login

SWI-Prolog SSL Interface
AllApplicationManualNameSummaryHelp

  • Documentation
    • Reference manual
    • Packages
      • SWI-Prolog SSL Interface
        • Introduction
        • library(ssl): Secure Socket Layer (SSL) library
        • library(crypto): Cryptography and authentication library
          • Introduction
          • Hashes and digests
          • Digital signatures
          • Asymmetric encryption and decryption
          • Symmetric encryption and decryption
        • XML cryptographic libraries
        • SSL Security
        • CRLs and Revocation
        • Example code
        • Acknowledgments

3 library(crypto): Cryptography and authentication library

author
Markus Triska
author
Matt Lilley

3.1 Introduction

This library provides bindings to functionality of OpenSSL that is related to cryptography and authentication, not necessarily involving connections, sockets or streams.

3.2 Hashes and digests

A hash, also called digest, is a way to verify the integrity of data. In typical cases, a hash is significantly shorter than the data itself, and already miniscule changes in the data lead to different hashes.

The hash functionality of this library subsumes and extends that of library(sha), library(hash_stream) and library(md5) by providing a unified interface to all available digest algorithms.

The underlying OpenSSL library (libcrypto) is dynamically loaded if either library(crypto) or library(ssl) are loaded. Therefore, if your application uses library(ssl), you can use library(crypto) for hashing without increasing the memory footprint of your application. In other cases, the specialised hashing libraries are more lightweight but less general alternatives to library(crypto).

The most important predicates to compute hashes are:

[det]crypto_data_hash(+Data, -Hash, +Options)
Hash is the hash of Data. The conversion is controlled by Options:
algorithm(+Algorithm)
One of md5, sha1, sha224, sha256 (default), sha384, sha512, blake2s256 or blake2b512. The BLAKE digest algorithms require OpenSSL 1.1.0 or greater.
encoding(+Encoding)
If Data is a sequence of character codes, this must be translated into a sequence of bytes, because that is what the hashing requires. The default encoding is utf8. The other meaningful value is octet, claiming that Data contains raw bytes.
hmac(+Key)
If this option is specified, a hash-based message authentication code (HMAC) is computed, using the specified Key which is either an atom or string. Any of the available digest algorithms can be used with this option. The cryptographic strength of the HMAC depends on that of the chosen algorithm and also on the key. This option requires OpenSSL 1.1.0 or greater.
Data is either an atom, string or code-list
Hash is an atom that represents the hash.
See also
hex_bytes/2 for conversion between hashes and lists.
[det]crypto_file_hash(+File, -Hash, +Options)
True if Hash is the hash of the content of File. For Options, see crypto_data_hash/3.

For further reasoning and conversion of digests in hexadecimal notation, the following bidirectional relation is provided:

[det]hex_bytes(?Hex, ?List)
Relation between a hexadecimal sequence and a list of bytes. Hex is an atom, string, list of characters or list of codes in hexadecimal encoding. This is the format that is used by crypto_data_hash/3 and related predicates to represent hashes. 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. When converting List to Hex, an atom is used to represent the sequence of hexadecimal digits.

Example:

?- hex_bytes('501ACE', Bs).
Bs = [80, 26, 206].

In addition, the following predicates are provided for building hashes incrementally. This works by first creating a context with crypto_context_new/2, then using this context with crypto_data_context/3 to incrementally obtain further contexts, and finally extract the resulting hash with crypto_context_hash/2.

[det]crypto_context_new(-Context, +Options)
Context is unified with the empty context, taking into account Options. The context can be used in crypto_data_context/3. For Options, see crypto_data_hash/3.
Context is an opaque pure Prolog term that is subject to garbage collection.
[det]crypto_data_context(+Data, +Context0, -Context)
Context0 is an existing computation context, and Context is the new context after hashing Data in addition to the previously hashed data. Context0 may be produced by a prior invocation of either crypto_context_new/2 or crypto_data_context/3 itself.

This predicate allows a hash to be computed in chunks, which may be important while working with Metalink (RFC 5854), BitTorrent or similar technologies, or simply with big files.

crypto_context_hash(+Context, -Hash)
Obtain the hash code of Context. Hash is an atom representing the hash code that is associated with the current state of the computation context Context.

The following hashing predicates work over streams:

[det]crypto_open_hash_stream(+OrgStream, -HashStream, +Options)
Open a filter stream on OrgStream that maintains a hash. The hash can be retrieved at any time using crypto_stream_hash/2. Available Options in addition to those of crypto_data_hash/3 are:
close_parent(+Bool)
If true (default), closing the filter stream also closes the original (parent) stream.
[det]crypto_stream_hash(+HashStream, -Hash)
Unify Hash with a hash for the bytes sent to or read from HashStream. Note that the hash is computed on the stream buffers. If the stream is an output stream, it is first flushed and the Digest represents the hash at the current location. If the stream is an input stream the Digest represents the hash of the processed input including the already buffered data.

3.3 Digital signatures

A digital signature is a relation between a key and data that only someone who knows the key can compute.

Signing uses a private key, and verifying a signature uses the corresponding public key of the signing entity. This library supports both RSA and ECDSA signatures. You can use load_private_key/3 and load_public_key/2 to load keys from files and streams.

In typical cases, we use this mechanism to sign the hash of data. See hashing (section 3.2). For this reason, the following predicates work on the hexadecimal representation of hashes that is also used by crypto_data_hash/3 and related predicates:

ecdsa_sign(+Key, +Data, -Signature, +Options)
Create an ECDSA signature for Data with EC private key Key. Among the most common cases is signing a hash that was created with crypto_data_hash/3 or other predicates of this library. For this reason, the default encoding (hex) assumes that Data is an atom, string, character list or code list representing the data in hexadecimal notation. See rsa_sign/4 for an example.

Options:

encoding(+Encoding)
Encoding to use for Data. Default is hex. Alternatives are octet, utf8 and text.
[semidet]ecdsa_verify(+Key, +Data, +Signature, +Options)
True iff Signature can be verified as the ECDSA signature for Data, using the EC public key Key.

Options:

encoding(+Encoding)
Encoding to use for Data. Default is hex. Alternatives are octet, utf8 and text.
[det]rsa_sign(+Key, +Data, -Signature, +Options)
Create an RSA signature for Data with private key Key. Options:
type(+Type)
SHA algorithm used to compute the digest. Values are sha1 (default), sha224, sha256, sha384 or sha512.
encoding(+Encoding)
Encoding to use for Data. Default is hex. Alternatives are octet, utf8 and text.

This predicate can be used to compute a sha256WithRSAEncryption signature as follows:

sha256_with_rsa(PemKeyFile, Password, Data, Signature) :-
    Algorithm = sha256,
    read_key(PemKeyFile, Password, Key),
    crypto_data_hash(Data, Hash, [algorithm(Algorithm),
                                  encoding(octet)]),
    rsa_sign(Key, Hash, Signature, [type(Algorithm)]).

read_key(File, Password, Key) :-
    setup_call_cleanup(
        open(File, read, In, [type(binary)]),
        load_private_key(In, Password, Key),
        close(In)).

Note that a hash that is computed by crypto_data_hash/3 can be directly used in rsa_sign/4 as well as ecdsa_sign/4.

[semidet]rsa_verify(+Key, +Data, +Signature, +Options)
Verify an RSA signature for Data with public key Key.

Options:

type(+Type)
SHA algorithm used to compute the digest. Values are sha1 (default), sha224, sha256, sha384 or sha512.
encoding(+Encoding)
Encoding to use for Data. Default is hex. Alternatives are octet, utf8 and text.

Signatures are also represented in hexadecimal notation, and you can use hex_bytes/2 to convert them to and from lists of bytes (integers).

3.4 Asymmetric encryption and decryption

The following predicates provide asymmetric RSA encryption and decryption. This means that the key that is used for encryption is different from the one used to decrypt the data:

[det]rsa_private_decrypt(+PrivateKey, +CipherText, -PlainText, +Options)
[det]rsa_private_encrypt(+PrivateKey, +PlainText, -CipherText, +Options)
[det]rsa_public_decrypt(+PublicKey, +CipherText, -PlainText, +Options)
[det]rsa_public_encrypt(+PublicKey, +PlainText, -CipherText, +Options)
RSA Public key encryption and decryption primitives. A string can be safely communicated by first encrypting it and have the peer decrypt it with the matching key and predicate. The length of the string is limited by the key length.

Options:

encoding(+Encoding)
Encoding to use for Data. Default is utf8. Alternatives are utf8 and octet.
padding(+PaddingScheme)
Padding scheme to use. Default is pkcs1. Alternatives are pkcs1_oaep, sslv23 and none. Note that none should only be used if you implement cryptographically sound padding modes in your application code as encrypting unpadded data with RSA is insecure
Errors
ssl_error(Code, LibName, FuncName, Reason) is raised if there is an error, e.g., if the text is too long for the key.
See also
load_private_key/3, load_public_key/2 can be use to load keys from a file. The predicate load_certificate/2 can be used to obtain the public key from a certificate.

3.5 Symmetric encryption and decryption

The following predicates provide symmetric encryption and decryption:

evp_decrypt(+CipherText, +Algorithm, +Key, +IV, -PlainText, +Options)
Decrypt the given CipherText, using the symmetric algorithm Algorithm, key Key, and iv IV, to give PlainText. CipherText, Key and IV should all be strings, and PlainText is created as a string as well. Algorithm should be an algorithm which your copy of OpenSSL knows about. Examples are:

  • aes-128-cbc
  • aes-256-cbc
  • des3

If the IV is not needed for your decryption algorithm (such as aes-128-ecb) then any string can be provided as it will be ignored by the underlying implementation

Options:

encoding(+Encoding)
Encoding to use for Data. Default is utf8. Alternatives are utf8 and octet.
padding(+PaddingScheme)
Padding scheme to use. Default is block. You can disable padding by supplying none here.

Example of aes-128-cbc encryption:

?- evp_encrypt("this is some input", 'aes-128-cbc', "sixteenbyteofkey",
               "sixteenbytesofiv", CipherText, []),
   evp_decrypt(CipherText, 'aes-128-cbc',
               "sixteenbyteofkey", "sixteenbytesofiv",
               RecoveredText, []).
CipherText = <binary string>
RecoveredText = "this is some input".
evp_encrypt(+PlainText, +Algorithm, +Key, +IV, -CipherTExt, +Options)
Encrypt the given PlainText, using the symmetric algorithm Algorithm, key Key, and iv IV, to give CipherText. See evp_decrypt/6.

ClioPatria (version V3.0.0-338-gc91dba5-DIRTY)