This section describes the implementation of PKCS#5 specification library. However we do not describe PKCS#5 itself and I don't think it is necessary to know it if you just want to use it.
This example is the simplest way to use.
(import (rnrs) (crypto) (rsa pkcs :5))
(define salt (string->utf8 "salt"))
(define iteration-count 1024)
(define pbe-parameter (make-pbe-parameter salt iteration-count))
(define pbe-key (generate-secret-key pbe-with-sha1-and-des "password"))
(define pbe-cipher (cipher pbe-with-sha1-and-des pbe-key
:parameter pbe-parameter))
(encrypt pbe-cipher (string->utf8 "This is an example."))
;; -> #vu8(254 229 155 168 167 192 249 43 33 192 161 215 28 117
;; 169 129 147 60 16 52 235 79 90 23)
(decrypt pbe-cipher
#vu8(254 229 155 168 167 192 249 43 33 192 161 215
28 117 169 129 147 60 16 52 235 79 90 23))
;; -> #vu8(84 104 105 115 32 105 115 32 97 110 32 101 120 97
;; 109 112 108 101 46)
The library itself defines simply its cipher and key generate methods. Hence user can use it with (crypto) library (see (crypto) - Cryptographic library)
NOTE: Currently the library only supports encryption and decryption, not MAC generation nor verification.
NOTE: When you create cipher object with PBE related algorithms, the you need
to pass :parameter
keyword to cipher
procedure, otherwise raises
an error.
This library exports PKCS#5 related cryptographic procedures.
The algorithms used in PBES1 encryption and decryption and key generation.
The names describe the using hash functions and cryptographic schemes. For
example, pbe-with-md5-and-des
uses MD5 hash and DES algorithm.
salt must be a bytevector.
iteration-count must be a non negative exact integer.
Creates a parameter for PBE key generation. salt is salt and iteration-count is the iteration count for key derivation.
algorithm must be one of the algorithms describes above.
Creates PBE secret key based on given password and algorithm.
These APIs are for users who want to create own PBE mechanism such as PKCS#12.
Implementation of PBKDF1 describes in PKCS#5 specification.
The arguments are plain text (bytevector), salt (bytevector), iteration count (non negative exact integer) and key length (non negative exact integer) respectively.
The keyword argument hash specifies which hash algorithm will be used. The default is SHA-1.
_ (prf (hash-algorithm HMAC :key P :hash hash))
Implementation of PBKDF2 describes in PKCS#5 specification.
The arguments are plain text (bytevector), salt (bytevector), iteration count (non negative exact integer) and key length (non negative exact integer) respectively.
The keyword argument hash specifies which hash algorithm will be used in PRF function. The default is SHA-1 and if you don't have any reasonable reason, this must not be changed.
The keyword argument prf specifies underlying pseudo random function which
must be hash object implemented with <user-hash-algorithm>
describes in
Custom hash algorithm. The default is HMAC and if you
don't have any reasonable reason, this must not be changed.
The implementation of key derive function. The required arguments are
the same as above pbkdf-1
and pbkdf-2
.
This procedure just calls given kdf with given arguments and returns derived key bytevector.
marker is user defined cipher type. key must be subclass of
<pbe-secret-key>
. parameter must be subclss of
<pbe-parameter>
.
This method is called in the initialize
method of
<pbe-cipher-spi>
and must return 2 values; the first one is derived key
as bytevector and second one is initial vector as bytevector.
The PKCS#5 encryption and decryption procedures require to derive both key and initial vector from given password and parameter (salt and iteration count). This method is used in PBE cipher to derive key and initial vector.
The purpose of this method is to re-use <pbe-cipher-spi>
. For example,
PKCS#12 can use this cipher, however it requires different key derivation
mechanism.
Since I could not find any standard implementation, Sagittarius actually does not support PBES2 encryption and decryption. However supporting it is not so difficult. This is the sample code to support it.
(import (rnrs) (clos user) (rfc hmac) (math))
(define-class <pbkef2-with-hmac-sha1-des3> () ())
(define pbkdf2-with-hmac-sha1-des3 (make <pbkef2-with-hmac-sha1-des3>))
(define-method generate-secret-key ((mark <pbkef2-with-hmac-sha1-des3>)
(password <string>))
(make <pbe-secret-key> :password password :hash (hash-algorithm HMAC)
:scheme DES3 :iv-size 8 :length 24
:type PKCS5-S2))
(register-spi pbkdf2-with-hmac-sha1-des3 <pbe-cipher-spi>)
And using this supported PBES2 cipher is like this;
(let* ((param (make-pbe-parameter (string->utf8 "saltsalt") 1024))
(key (generate-secret-key pbkdf2-with-hmac-sha1-des3 "password"))
(pbe-cipher (cipher pbkdf2-with-hmac-sha1-des3 key :parameter param))
(ciphertext (encrypt pbe-cipher (string->utf8 "This is an example."))))
(utf8->string (decrypt pbe-cipher ciphertext)))
I suppose this is correct, but I could not find any implementation which supports PBES2. I usually test with JCE, so if you have some recommendation, please let me know.