Cryptographic Functions
This module contains functions to perform cryptographic operations in XQuery. The cryptographic module was based on a draft of the EXPath Cryptographic Module. It provides the following functionality: creation of message authentication codes (HMAC), derivation of keys from passwords, encryption and decryption, and creation and validation of XML Digital Signatures.
All functions are in the http://expath.org/ns/crypto namespace, to which the crypto prefix is statically bound.
All errors are in the http://expath.org/ns/error namespace, to which the experr prefix is statically bound.
| Signature | crypto:hmac( $value as (xs:string | xs:base64Binary | xs:hexBinary), $key as (xs:string | xs:base64Binary | xs:hexBinary), $algorithm as xs:string, $encoding as xs:string? := ()) as xs:string |
|---|
| Summary | Creates an authentication code for the specified $value via a cryptographic hash function:
$value must be a string or binary item.$key must not be empty.$algorithm describes the hash algorithm which is used for encryption. Currently supported are md5, sha1, sha256, sha384, sha512. Default is md5.$encoding must either be hex or base64; it specifies the encoding of the returned authentication code. Default is base64.
|
|---|
| Errors | CX0013 | The hashing algorithm is not supported. | CX0014 | The encoding method is not supported. | CX0019 | The secret key is invalid. |
|
|---|
| Examples | crypto:hmac('message', 'secretkey', 'md5', 'hex') Return the message authentication code 34D1E3818B347252A75A4F6D747B21C2. |
|---|
Added: New function.
| Signature | crypto:pbkdf2( $password as xs:string, $salt as (xs:string | xs:base64Binary | xs:hexBinary), $iterations as xs:integer, $length as xs:integer, $algorithm as xs:string? := ()) as xs:hexBinary |
|---|
| Summary | Derives a key from the specified $password with PBKDF2 (Password-Based Key Derivation Function 2). The function is suited for storing passwords, as each derivation takes a configurable amount of time:
$salt must not be empty. It should be random and unique for each password; it can be stored along with the derived key.$iterations is the number of hash iterations. A high value (600,000 or more for SHA-256) slows down brute-force attacks.$length is the length of the derived key in bytes.$algorithm is the hash algorithm of the underlying HMAC. Supported are SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224 and SHA-512/256. Default is SHA-256.
|
|---|
| Errors | CX0013 | The hashing algorithm is not supported. | CX0019 | The secret key is invalid. |
|
|---|
| Examples | crypto:pbkdf2('password', 'salt', 4096, 32) Return the derived key C5E478D59288C841AA530DB6845C4C8D962893A001CE4E11A4963873AA98134A.
let $salt := random:uuid()
let $key := crypto:pbkdf2('secret', $salt, 600000, 32)
return db:put-value('users', { 'salt': $salt, 'key': $key }, 'jane') Store the salt and the derived key of a user password; a login attempt is checked by deriving the key again with the stored salt. |
|---|
The encryption and decryption functions underlie several limitations:
- Available
symmetric algorithms (the same secret key is used for encryption and decryption) are AES (CBC mode with PKCS5Padding) and AES-GCM (GCM mode; authenticated encryption, which detects tampered data on decryption). The key must have 16, 24 or 32 bytes. - The only
asymmetric algorithm is RSA (OAEP padding with SHA-256). Data is encrypted with a public key and decrypted with the corresponding private key. The keys are passed as strings in PEM format (-----BEGIN PUBLIC KEY-----, -----BEGIN PRIVATE KEY-----) or as binary items in DER format (X.509 for public keys, PKCS #8 for private keys). The data must be shorter than the key size minus 66 bytes, e.g. 190 bytes for a 2048-bit key. - The result of a symmetric encryption using the same message, algorithm and key looks different each time it is executed. This is due to a random initialization vector (IV) which is prepended to the message and simply increases security.
- As the IV has to be passed along with the encrypted message somehow, data which has been encrypted by the
crypto:encrypt function in BaseX can only be decrypted by calling the crypto:decrypt function.
Updated: AES-GCM and RSA added; DES removed.
| Signature | crypto:encrypt( $value as (xs:string | xs:base64Binary | xs:hexBinary), $type as xs:string, $key as (xs:string | xs:base64Binary | xs:hexBinary), $algorithm as xs:string) as xs:base64Binary |
|---|
| Summary | Encrypts the specified $value with the specified key:
$value must be a string or binary item.$type must be symmetric or asymmetric.$key is the secret key (symmetric) or the public key (asymmetric). It must be a string or binary item.$algorithm must be AES or AES-GCM (symmetric), or RSA (asymmetric).
|
|---|
| Errors | CX0016 | No such padding. | CX0017 | Incorrect padding. | CX0018 | The encryption type is not supported. | CX0019 | The secret key is invalid. | CX0020 | Illegal block size. | CX0021 | The algorithm is not supported. |
|
|---|
| Examples | crypto:encrypt('message', 'symmetric', 'keykeykeykeykeyk', 'AES-GCM') Encrypt input data.
crypto:encrypt('message', 'asymmetric', file:read-text('public.pem'), 'RSA') Encrypt input data with a public key, e.g. created via openssl genpkey -algorithm RSA -out private.pem and openssl pkey -in private.pem -pubout -out public.pem. |
|---|
Updated: AES-GCM and RSA added; DES removed.
| Signature | crypto:decrypt( $value as (xs:string | xs:base64Binary | xs:hexBinary), $type as xs:string, $key as (xs:string | xs:base64Binary | xs:hexBinary), $algorithm as xs:string) as xs:string |
|---|
| Summary | Decrypts the specified $value with the specified key:
$value must be a string or binary item.$type must be symmetric or asymmetric.$key is the secret key (symmetric) or the private key (asymmetric). It must be a string or binary item.$algorithm must be AES or AES-GCM (symmetric), or RSA (asymmetric).
|
|---|
| Errors | CX0016 | No such padding. | CX0017 | Incorrect padding. | CX0018 | The encryption type is not supported. | CX0019 | The secret key is invalid. | CX0020 | Illegal block size. | CX0021 | The algorithm is not supported. |
|
|---|
| Examples | let $encrypted := crypto:encrypt('message', 'symmetric', 'keykeykeykeykeyk', 'AES-GCM')
return crypto:decrypt($encrypted, 'symmetric', 'keykeykeykeykeyk', 'AES-GCM') Decrypts the input and returns message. |
|---|
XML Signatures are used to sign data. In our case, the data which is signed is an XQuery node. The following example shows the basic structure of an XML signature.
XML Signature
<Signature>
<SignedInfo>
<CanonicalizationMethod/>
<SignatureMethod/>
<Reference>
<Transforms/>
<DigestMethod/>
<DigestValue/>
</Reference>
<Reference/>
</SignedInfo>
<SignatureValue/>
<KeyInfo/>
<Object/>
</Signature>
- SignedInfo contains or references the signed data and lists algorithm information
- Reference references the signed node
- Transforms contains transformations (i.e. XPath expressions) that are applied to the input node in order to sign a subset
- DigestValue holds digest value of the transformed references
- SignatureValue contains the Base64 encoded value of the encrypted digest of the
SignedInfo element - KeyInfo provides information on the key that is used to validate the signature
- Object contains the node which is signed if the signature is of type
enveloping
Signature Types
Depending on the signature type, the signature element is either placed as a child of the signed node (enveloped type), or directly contains the signed node (enveloping type). Detached signatures are so far not supported.
Digital Certificate
The generate-signature function allows to pass a digital certificate. This certificate holds parameters that allow to access key information stored in a Java key store which is then used to sign the input document. Passing a digital certificate simply helps re-using the same key pair to sign and validate data. The digital certificate is passed as a node and has the following form:
<digital-certificate>
<keystore-type>JKS</keystore-type>
<keystore-password>...</keystore-password>
<key-alias>...</key-alias>
<private-key-password>...</private-key-password>
<keystore-uri>...</keystore-uri>
</digital-certificate>
Updated: New algorithms RSA_SHA256, RSA_SHA512 and DSA_SHA256; new defaults SHA256 and RSA_SHA256.
| Signature | crypto:generate-signature( $node as xnode(), $canonicalization as xs:string, $digest as xs:string, $signature as xs:string, $prefix as xs:string, $type as xs:string, $ext1 as item() := (), $ext2 as xnode() := ()) as document-node() |
|---|
| Summary | Generates a signature:
$canonicalization must either be inclusive-with-comments, inclusive, exclusive-with-comments or exclusive. Default is inclusive-with-comments.$digest must be one of the following: SHA1, SHA256 or SHA512. Default is SHA256.$signature must be one of the following: RSA_SHA1, RSA_SHA256, RSA_SHA512, DSA_SHA1 or DSA_SHA256. Default is RSA_SHA256.- Signatures that were created with
SHA1 are rejected by the secure validation of current Java versions, and can no longer be validated with crypto:validate-signature. $prefix may be empty and prefixes the Signature element accordingly.$type is the signature type. It must either be enveloped or enveloping (detached signatures are not supported so far). Default is enveloped.$ext1 may either be an XPath expression or a digital certificate.- If
$ext2 is specified as well, $ext1 is an arbitrary XPath expression which specifies a subset of the document that is to be signed, and $ext2 is the digital certificate used to sign the input document.
|
|---|
| Errors | CX0001 | The canonicalization algorithm is not supported. | CX0002 | The digest algorithm is not supported. | CX0003 | The signature algorithm is not supported. | CX0004 | The XPath expression is invalid. | CX0005 | The root element of argument $digital-certificate must have the name 'digital-certificate'. | CX0007 | The keystore is null. | CX0012 | Cannot find key for alias in given keystore. | CX0023 | An invalid certificate alias is specified. Added to the official specification. | CX0024 | The algorithm is invalid. Added to the official specification. | CX0025 | Signature cannot be processed. Added to the official specification. | CX0026 | Keystore cannot be processed. Added to the official specification. | CX0027 | An I/O Exception occurred. Added to the official specification. | CX0028 | The specified signature type is not supported. Added to the official specification. |
|
|---|
| Signature | crypto:validate-signature( $node as xnode()) as xs:booleancreate |
|---|
| Summary | Checks if the specified $node contains a Signature element and whether the signature is valid. In this case true is returned. If the signature is invalid the function returns false. create permission is required if the signature references external resources. |
|---|
| Errors | |
|---|
| Code | Description |
|---|
CX0001 | The canonicalization algorithm is not supported. |
CX0002 | The digest algorithm is not supported. |
CX0003 | The signature algorithm is not supported. |
CX0004 | The XPath expression is invalid. |
CX0005 | The root element of argument $digital-certificate must have the name 'digital-certificate'. |
CX0006 | The child element of argument $digital-certificate having position $position must have the name $child-element-name. |
CX0007 | The keystore is null. |
CX0008 | I/O error while reading keystore. |
CX0009 | Permission denied to read keystore. |
CX0010 | The keystore URL is invalid. |
CX0011 | The keystore type is not supported. |
CX0012 | Cannot find key for alias in given keystore. |
CX0013 | The hashing algorithm is not supported. |
CX0014 | The encoding method is not supported. |
CX0015 | Cannot find Signature element. |
CX0016 | No such padding. |
CX0017 | Incorrect padding. |
CX0018 | The encryption type is not supported. |
CX0019 | The secret key is invalid. |
CX0020 | Illegal block size. |
CX0021 | The algorithm is not supported. |
CX0023 | An invalid certificate alias is specified. Added to the official specification. |
CX0024 | The algorithm is invalid. Added to the official specification. |
CX0025 | Signature cannot be processed. Added to the official specification. |
CX0026 | Keystore cannot be processed. Added to the official specification. |
CX0027 | An I/O Exception occurred. Added to the official specification. |
CX0028 | The specified signature type is not supported. Added to the official specification. |
Version 13.0Version 9.3Version 7.0
⚡Generated with XQuery