
Bigloo provides several functions for encrypting and decrypting documents.
These are described in the chapter. Unless explicitly mentioned all functions
presented in this document are accessible via the crypto library. None of the cryptographic functions are protected against timing attacks.
No effort has been spent on protecting used memory.Here is an example of a module that uses this library:
;; Encrypt a string using AES.
(module aesencrypt
(library crypto)
(main main))
(define (main argv)
(when (and (pair? (cdr argv)) (pair? (cddr argv)))
(let ((encrypt? (string=? "e" (cadr argv)))
(passwd (caddr argv))
(input (readstring)))
(if encrypt?
(display (encrypt 'aes input passwd))
(display (decrypt 'aes input passwd))))))

15.1 Symmetric Block Ciphers

Bigloo supports some common block ciphers. Block ciphers work on blocks of fixed
size. A mode of operation defines the way bigger input is handled. For
instance in ECB (Electronic Codebook mode) the blocks are all encrypted
separately, whereas CBC (CipherBlock Chaining) chains all blocks. All modes that chain the blocks need an IV (Initial Vector) to ``bootstrap''
the chaining. Block ciphers by themselves can only work on full blocks. Some modes are
constructed in a way that even incomplete blocks can be safely processed. For the
remaining blocks a padding function needs to be given. Most block ciphers only work with keys of specific length. The following functions
take passwords (strings of arbitrary length) as input, and preprocess the given
password by a :string>key function. The result must then be of correct
length.
encrypt::bstring cipher plain password [:string>key] [:mode 'cfb] [:IV #f] [:pad 'none] [:nonceinit!] [:nonceupdate!]  Bigloo Cryptography procedure 
encryptstring::bstring cipher plaintext::bstring password [:string>key] [:mode 'cfb] [:IV #f] [:pad 'none] [:nonceinit!] [:nonceupdate!]  Bigloo Cryptography procedure 
encryptmmap::bstring cipher plaintext::mmap password [:string>key] [:mode 'cfb] [:IV #f] [:pad 'none] [:nonceinit!] [:nonceupdate!]  Bigloo Cryptography procedure 
encryptport::bstring cipher plaintext::inputport password [:string>key] [:mode 'cfb] [:IV #f] [:pad 'none] [:nonceinit!] [:nonceupdate!]  Bigloo Cryptography procedure 
encryptfile::bstring cipher filename::bstring password [:string>key] [:mode 'cfb] [:IV #f] [:pad 'none] [:nonceinit!] [:nonceupdate!]  Bigloo Cryptography procedure 
encryptsendchars cipher in::inputport out::outputport password [:string>key] [:mode 'cfb] [:IV #f] [:pad 'none] [:nonceinit!] [:nonceupdate!]  Bigloo Cryptography procedure 
The procedure encrypt encrypts its input using the chosen cipher . The result is returned as string.
encrypt dispatches depending on the type of plain . Strings are processed by encryptstring (and
not encryptfile ).
The function encryptsendchars reads from an inputport in and encrypts its output directly
into an outputport out .
The symbol cipher can be one of:
des : Data Encryption Standard (DES). DES works on blocks of 64 bits. DES requires keys of length 64 (bits),
but only 56 of these bits are actually used. Bigloo's implementation therefore accepts both.
DES is considered to be insecure and its usage is discouraged.
des3 : Triple DES, Triple Data Encryption Algorithm (DES3, TDEA).
DES3 works on blocks of 64 bits. DES3 requires keys of
length 128 or 192 (bits), but only 112/168 of these bits are actually used. Bigloo's
implementation therefore accepts the smaller keys too.
Bigloo's DES3 implementation has been changed with release 3.4b. Earlier
versions did not use the full key for en/decryption.
desnp : Same as des , but the initial and final permutations are not performed.
des3np : Same as des3 , but the initial and final permutations are not performed.
aes : Advanced Encryption Standard (AES). AES works on blocks of 128 bits. AES requires
keys of length 128, 192 or 256 bits.
cast128 : CAST128 (CAST5). CAST128 works on blocks of 64 bits. CAST128 requires a
keylength of 40128 bits.
idea : International Data Encryption Algorithm (IDEA). IDEA works on blocks of 64 bits.
It requires keys of length 128 (in bits). IDEA is patented in many countries (including
the USA and most European countries) but it is free for noncommercial use.
The given password must be a string. An optional parameter :string>key should transform this
password so that it has the correct length for the cipher. A small list of possible functions are
provided in the String to Key section.
By default string>keyhash with SHA1 will be used. The keylength will depend
on the chosen cipher:
des : 56 bits.
des3 : 112 bits.
desnp : Same as des .
des3np : Same as des3 .
aes : 192 bits.
cast128 : 128 bits.
idea : 128 bits.
Bigloo supports the following block cipher modes (:mode ):
ecb : Electronic codebook.
cbc : Cipherblock chaining.
pcbc : Propagating cipherblock chaining.
cfb : Cipher feedback.
ofb : Output feedback.
ctr : Counter.
By default cfb is chosen.
Electronic codebook mode en/decodes each block independently and is hence the
closest to the block cipher. It is however inherently unsafe as blocks with
the same content are encrypted to the same output.
With the exception of ecb all other modes can be initialized with an IV
(Initialization vector). If :IV is false, then a random one will be generated.
During encryption this randomly generated IV will be prefixed to the result. When
calling the decryption routine without any IV the procedure will use the first block
of the input as IV.
In ctr (counter) mode the IV parameter serves as nonce. Two additional
keyparameters :nonceinit and :nonceupdate are then used to
initialize and update the blocksized nonce string. Before encrypting the first block
nonceinit will be invoked with an empty blocksized string and the initial
nonce (IV). It must initialize the string with the nonce. For each block
nonceupdate will be called with the string, the nonce, and the number of
already encrypted blocks (hence 0 at the very beginning). By default
nonceinit takes the IVstring and blits it into the given string.
nonceupdate simply increments the string (treating the given string as
one big number).
Note that the initial nonce (passed using IV) may be of any type. As long as
nonceinit and nonceupdate correctly initialize and update the
passed string.
The input's length of modes ecb , cbc and pcbc must be a
multiple of the blocksize. Should this not be the case a padding algorithm
must be specified (:pad ). Currently are implemented (examples for
hexadecimal string ``DD'' and cipher block size 4):
none : No padding. Raises an error should the input not be a multiple.
bit : Bit padding. Add a '1' bit and then '0' bits.
Example: ``DD 80 00 00''.
ansix.923 : Byte padding. Fill with #x00s followed by the number of added
bytes (the counter inclusive). Example: ``DD 00 00 03''.
iso10126 : Fill with random characters followed by the number of added
bytes (the counter inclusive). Example: ``DD 42 31 03''.
pkcs7 : Fill with the number of added bytes. Example: ``DD 03 03 03''.
zero : Fill with zeros. This is only reversible if the input is guaranteed
not to finish with a zero character. Example: ``DD 00 00 00''.
Alternatively users can supply their own (un)pad functions (instead of a symbol). The
signature of a padding function is (pad::bool str::bstring validchars::long) . It
receives the last block of the input. Should the input be of correct length then the an
empty block will be sent to the padding function. validchars indicates the number
of read characters. It ranges from 0 to blocksize1. The
padding function should fill the block and return #t if this last block should
be encoded. By returning #f the last block will be discarded. This makes
only sense if validchars was equal to 0.
The unpadding procedure has the signature (unpad::long str::bstring) . The
input string will have the length of the blocksize. The unpadding function may
modify the string and must return the number of characters that are valid.

decrypt::bstring cipher ciphertext password [:string>key] [:mode 'cfb] [:IV #f] [:pad 'none] [:nonceinit!] [:nonceupdate!]  Bigloo Cryptography procedure 
decryptstring::bstring cipher ciphertext::bstring password [:string>key] [:mode 'cfb] [:IV #f] [:pad 'none] [:nonceinit!] [:nonceupdate!]  Bigloo Cryptography procedure 
decryptmmap::bstring cipher ciphertext::mmap password [:string>key] [:mode 'cfb] [:IV #f] [:pad 'none] [:nonceinit!] [:nonceupdate!]  Bigloo Cryptography procedure 
decryptport::bstring cipher ciphertext::inputport password [:string>key] [:mode 'cfb] [:IV #f] [:pad 'none] [:nonceinit!] [:nonceupdate!]  Bigloo Cryptography procedure 
decryptfile::bstring cipher filename::bstring password [:string>key] [:mode 'cfb] [:IV #f] [:pad 'none] [:nonceinit!] [:nonceupdate!]  Bigloo Cryptography procedure 
decryptsendchars cipher in::inputport out::outputport password [:string>key] [:mode 'cfb] [:IV #f] [:pad 'none] [:nonceinit!] [:nonceupdate!]  Bigloo Cryptography procedure 
Counterpart to the encryption functions. With the same parameters the decrypt function will
decrypt the result of an encrypt call. Without :IV (Initial Vector) the decrypt function
will use the first block as IV.

For compatibility the following functions remain in Bigloo. They are in the default
library and not inside the crypto library.
aesctrencrypt text password [nbits 128]  bigloo procedure 
aesctrencryptmmap mmap password [nbits 128]  bigloo procedure 
aesctrencryptstring string password [nbits 128]  bigloo procedure 
aesctrencryptport iport password [nbits 128]  bigloo procedure 
aesctrencryptfile filename password [nbits 128]  bigloo procedure 
These functions are equivalent to a call to aesencrypt with mode set to
ctr and a special :string>key parameter. The optional
argument nbits must either be 128 , 192 , or 256 and
determines the size of the key.

aesctrdecrypt text password [nbits 128]  bigloo procedure 
aesctrdecryptmmap mmap password [nbits 128]  bigloo procedure 
aesctrdecryptstring string password [nbits 128]  bigloo procedure 
aesctrdecryptport iport password [nbits 128]  bigloo procedure 
aesctrdecryptfile filename password [nbits 128]  bigloo procedure 
Counterpart to aesctrencrypt .

The following string>key algorithms take a password string and transform it to
a key string of a given length. In all the functions the len is expressed in
bytes.
string>keyzero str len  Bigloo Cryptography procedure 
If the length of the input string str is greater or equal to len
bytes then the first str characters are returned. Otherwise str is
suffixed with '0' (#a000 ) characters.

string>keyhash str len hashfun  Bigloo Cryptography procedure 
The input string str is run through the given hash function hashfun .
The result is then concatenated multiple times (with itself) until a string of the
len bytes is obtained.
In the following example we encrypt somemessage using a
password "my password" . The password will be transformed to
256 bits (32 bytes) using the string>key256 function.
(define (string>key256 password)
(string>keyhash password 32
(lambda (str) (stringhexintern (sha1sum str)))))
(encrypt 'aes somemessage "my password" :string>key string>key256)

Note that the following example yields an identical result:
(define (string>key256 password)
(string>keyhash password 32
(lambda (str) (stringhexintern (sha1sum str)))))
(encrypt 'aes somemessage (string>key256 "my password")
:string>key (lambda (x) x))


string>keysimple str len hashfun  Bigloo Cryptography procedure 
This function implements the simple s2k algorithm of OpenPGP (RFC 2440). Basically
str is run through the hashfun several times until the concatenation of
the results is long enough. At each iteration the string is prefixed with
count '0'bytes (where count is the iteration counter).

string>keysalted str len hashfun salt  Bigloo Cryptography procedure 
This function implements the salted s2k algorithm of OpenPGP (RFC 2440).
Similar to string>keysimple but the input string is first prefixed with
salt .

string>keyiteratedsalted str len hashfun salt count  Bigloo Cryptography procedure 
This function implements the iterated salted s2k algorithm of OpenPGP (RFC 2440).
The variable count must be a long. This algorithm is an extension of
string>keysalted where the hash function is applied
repeatedly.
This function has changed with release 3.4b. Earlier
versions could be incompatible with RFC 2440.

15.2 Public Key Cryptography

15.2.1 Rivest, Shamir, and Adleman (RSA)

Bigloo's implementation of RSA is based on RFC 3447, PKCS #1 v2.1. It does
not feature multiprime RSA, though. Bigloo's implementation is not secure against timing attacks. Furthermore
some error codes might reveal information to attackers.
15.2.1.1 RSA Keys
There are two kinds of RSA keys inside Bigloo: complete and partial keys.
A complete key contains the information of both the public and the private
key (together with other information that could be reconstructed out of
the private key). A partial key just contains the modulus and the private
or public exponent.
RSAKey  Bigloo Cryptography class 
CompleteRSAKey  Bigloo Cryptography class 
(class RsaKey modulus::bignum exponent::bignum)
(finalclass CompleteRsaKey::RsaKey
;; for the completersakey "exponent" takes the role of 'd'
e::bignum p::bignum q::bignum
exp1::bignum ;; d mod (p1)
exp2::bignum ;; d mod (q1)
coeff::bignum) ;; (inverse of q) mod p


RSA keys can be read and written using readpemkey and
writepemkey ( PEM).
generatersakey [:key 1024] [:showtrace]  Bigloo Cryptography procedure 
This function generates a new RSA key (with its public and private components).
Do not use this function for critical applications. No special effort has been
undertaken to guarantee the randomness of the generated prime numbers, nor to
weed out insecure keys.

Complete keys can be accessed using the following functions:
extractpublicrsakey completekey  Bigloo Cryptography procedure 
Returns the public partial key of the given complete key.
This procedure is implemented as follows:
(define (extractpublicrsakey::RsaKey key::CompleteRsaKey)
(withaccess::CompleteRsaKey key (modulus e)
(makeRsaKey modulus e)))


extractprivatersakey completekey  Bigloo Cryptography procedure 
Returns the private partial key of the given complete key.

rsakey=? key1 key2  Bigloo Cryptography procedure 
Returns true if the two keys have the same modulus and public exponent.
The exponent of a partial key is considered to be public.

rsakeylength key  Bigloo Cryptography procedure 
Returns the key length in bytes.

15.2.1.2 RSA basic operations
RSA only works on bignums (up to the size of the modulus). The following
procedures implement basic encryption, decryption, signing and
signature verification.
rsaencrypt key m  Bigloo Cryptography procedure 
Encrypts the bignum m using the given key. If the key is a complete
key then its public exponent is used. For partial keys only one
exponent is available (which is assumed to be the public 'e' of the
recipient). The result is again a bignum.

rsadecrypt key c  Bigloo Cryptography procedure 
Decrypts the bignum c using the given key. If the key is a complete
key then its private exponent is used. For partial keys only one exponent
is available (which is assumed to be the private 'd').
The result is again a bignum.

rsasign k m  Bigloo Cryptography procedure 
Signs the bignum m using key k . Uses the private exponent
of complete keys. The result is a bignum.

rsaverify k m s  Bigloo Cryptography procedure 
Verifies the signature s . Returns true if s is the
signature of m . The key k should be the public
key of the signer.

15.2.1.3 Examples
In this section we will present an example of using RSA. Let's start by generating an RSA key in openssl:
$ openssl genrsa out my_rsa_key.pem 1024

Our key will have 1024 bits (for the public modulus), and therefore
RSA will only be able to work with bignums up to 1024 bits
(128 bytes). Now some Bigloo code that uses this key. Start by loading the library.
(module rsaexample (library crypto))

Now read the key:
(define *key* (readpemkey "my_rsa_key.pem"))
(define *publickey* (extractpublicrsakey *key*))

The public portion of the key can be distributed:
;; publish the *publickey*:
(writepemkeystring *publickey*)

Now let's sign the message ``My Important Message''. This message is
sufficiently short to be signed directly, but in general it is better
to get a hash of the message:
(define msghash (sha1sum "my message"))
(define msghashbignum (octetstring>bignum msghash))

The result of sha1sum returns a human readable representation
of the hash. It would hence be possible to transform it back to
an internal representation before applying the
octetstring>bignum function:
(define msghashbignum (octetstring>bignum (stringhexintern msghash)))

In our case both variants are small enough to fit into our keys. The latter version
is however more often used. Now that we have a message hash in bignum form we can sign it.
(define signature (rsasign *key* msghashbignum))

The signature is again in bignum form. If needed there are several ways to transform
it into stringform (for instance bignum>string or bignum>octetstring ). The signature can now be distributed. Anyone wanting to verify the signature
simply has to create the same messagehash and call rsaverify with our
public key:
(rsaverify *publickey* msghashbignum signature) => #t

Encryption and decryption work in a similar way. Suppose someone (let's say ``Alice'') wants to send us the following secret message
``Cryptography''. The encryption and decryption functions work, similar
to the signature functions, on bignums. We could, as before, simply
transform this short string into a bignum and directly encrypt
the bignum. This approach would however not work for longer strings. In the following we
will present the generic version that works with strings of any size. Public key cryptography is relatively slow and Alice thus starts by encrypting our
message a fast block cipher with a ``random'' password:
(define encrypted (encrypt 'aes "Cryptography" "my random password"))

Alice can already send us the encrypted message. We will just not yet be able
to decrypt it, as we don't have the random password yet. Alice now takes her random password string and encrypts it with our public key:
(define encryptedkey (rsaencrypt *publickey* (octetstring>bignum "my random password")))

Alice simply sends us the encryptedkey . On our side we can now
decrypt the key:
(define aeskey (bignum>octetstring (rsadecrypt *key* encryptedkey)))

We can now decrypt the previously received message:
(decrypt 'aes aeskey encrypted) => "Cryptography"

15.2.1.4 RSA RFC 3447
The following functions have been defined in RFC 3447.
RSAEP k m  Bigloo Cryptography procedure 
RSADP k c  Bigloo Cryptography procedure 
RSASP1 k m  Bigloo Cryptography procedure 
RSAVP1 k s  Bigloo Cryptography procedure 
These are the RFC 3447 names for encryption, decryption, signature and
signature verification. Note that the verification does not receive the
original message as parameter.
In fact rsaverify is implemented as follows:
(define (rsaverify k m s)
(=bx m (RSAVP1 k s)))


PKCS1v1.5pad mstr keylen mode  Bigloo Cryptography procedure 
PKCS1v1.5unpad emstr mode  Bigloo Cryptography procedure 
Pads (resp. unpads) the given string using PKCS1v1.5 specifications.
Mode must be 0, 1 or 2.

RSAESPKCS1v1.5encryptt key mstr  Bigloo Cryptography procedure 
RSAESPKCS1v1.5decrypt key cstr  Bigloo Cryptography procedure 
RSASSAPKCS1v1.5sign key msgstr [:hashalgo 'sha1]  Bigloo Cryptography procedure 
RSASSAPKCS1v1.5verify key msgstr Sstr  Bigloo Cryptography procedure 
RSASSAPKCS1v1.5signbignum key msgstr [:hashalgo 'sha1]  Bigloo Cryptography procedure 
RSASSAPKCS1v1.5verifybignum key msgstr S  Bigloo Cryptography procedure 
RSAESPKCS1v1.5 functions work on strings. However their length is
limited by the size of the modulus (to be exact: by keylen  11).
The bignum functions skip the last step of converting the
internal bignum to strings.
The optional :hashalgo must be either sha1 or md5
(RFC 3447 allows other hash algorithms, but they are not yet implemented).

RSAESOAEPencrypt key mstr [:label ""]  Bigloo Cryptography procedure 
RSAESOAEPdecrypt key cypherstr [:label ""]  Bigloo Cryptography procedure 
RSASSAPSSsign key msgstr  Bigloo Cryptography procedure 
RSASSAPSSverify key msgstr sigstr  Bigloo Cryptography procedure 
These functions pad, mask, etc the input string before they perform their
operation on them. See RFC 3447 for more information.

15.2.2 Digital Signature Algorithm (DSA)

Bigloo has rudimentary (but usually sufficient) support for DSA.
While it is not possible to generate new DSA keys inside Bigloo
one can sign or verify with Bigloo. DSA keys can be read and written using readpem ( PEM). For consistency with RSA we have named DSA keys in a similar way as
the RSA keys. The public part of a DSA key can be found in the class
DSAKey while the private part is added in the
CompleteDSAKey subclass.
DSAKey  Bigloo Cryptography class 
CompleteDSAKey  Bigloo Cryptography class 
(class DsaKey
p::bignum q::bignum g::bignum y::bignum)
(finalclass CompleteDsaKey::DsaKey
x::bignum)) ;; the private key


extractpublicdsakey completekey  Bigloo Cryptography procedure 
Returns a DSAKey without the private x .

dsasign m key  Bigloo Cryptography procedure 
Signs the bignum m using the private dsa key key . The
result are two values: r and s .
A typical call to dsasign is hence of the following form
(receive (r s)
(dsasign secretkey hashedmsgbignum)
(processsignature r s))


dsaverify m key r s  Bigloo Cryptography procedure 
Verifies a signature (consisting of r and s ).

DSA works very similar to RSA. Have a look at RSA's example section.
Bigloo supports ElGamal encryption (but not signing). Bigloo's
implementation is minimal. For consistency with RSA ElGamal keys are similarly named as their
RSA counterparts.
ElGamalKey  Bigloo Cryptography class 
CompleteElGamalKey  Bigloo Cryptography class 
(class ElGamalKey
p::bignum
g::bignum
y::bignum)
(finalclass CompleteElGamalKey::ElGamalKey
x::bignum)) ;; the private key


extractpublicelgamalkey completekey  Bigloo Cryptography procedure 
Returns a copy of the public part (as ElGamal Key ).

elgamalencrypt key m  Bigloo Cryptography procedure 
Encrypts the bignum m using the given public key. The result are two
values c1 and c2 .
Note that ElGamal encryption needs random bytes for every encryption. This
means that this function may return different results with the same parameters.
It furthermore implies that the result is insecure if the operating system
provides bad random numbers, or if Bigloo's randomnumber generation is buggy.
For critical applications be sure to verify both requirements.

elgamaldecrypt completekey c1 c2  Bigloo Cryptography procedure 
Decrypts an ElGamal encrypted message (consisting of the two bignums
c1 and c2 ) with the given private key.

elgamalkeylength key  Bigloo Cryptography procedure 
Returns the key length in bytes.

ElGamal works very similar to RSA. Have a look at RSA's example section.
Bigloo is able to read and write RSA and DSA keys in PEM format. This is
the default format used by OpenSSL. The following example creates a new DSA key pair in OpenSSL and stores it
in PEM format.
$ openssl dsaparam 1024 out /tmp/dsaparam
$ openssl gendsa /tmp/dsaparam

readpemkey in  Bigloo Cryptography procedure 
readpemkeyport inputport  Bigloo Cryptography procedure 
readpemkeyfile filename  Bigloo Cryptography procedure 
readpemkeystring str  Bigloo Cryptography procedure 
These functions will read a PEM encoded key. The encoded file may contain
a private or public RSA key, or a private or public DSA key.
The procedure readpemkey accepts inputports and strings. In the case
of a string it will invoke readpemkeyfile
(and not readpemkeystring ).

writepemkey key out [publickeyonly?]  Bigloo Cryptography procedure 
writepemkeyport key out [publickeyonly?]  Bigloo Cryptography procedure 
writepemkeyfile key out [publickeyonly?]  Bigloo Cryptography procedure 
writepemkeystring key [publickeyonly?]  Bigloo Cryptography procedure 
These functions write the given key. The key may be a private/public
RSA/DSA key.
The procedure writepemkey accepts outputports and strings as
out parameter. If out is a string it will delegate to
writepemkeyfile .

Bigloo implements parts of OpenPGP (RFC 2440, RFC 4880). All OpenPGP
functions are accessible via the openpgp library. Here is an example of a module that uses this library:
;; Encrypt a string using openpgp default encryption.
(module pgpencrypt
(library openpgp)
(main main))
(define (main argv)
(when (and (pair? (cdr argv)) (pair? (cddr argv)))
(let ((encrypt? (string=? "e" (cadr argv)))
(passwd (caddr argv))
(input (readstring)))
(if encrypt?
(display (pgpwritestring (pgpencrypt input
'() ;; no public keys
(list passwd))))
(let ((composition (pgpreadstring input)))
(display (pgpdecrypt composition
:passkeyprovider (lambda () passwd))))))))

pgpreadstring str  Bigloo OpenPGP procedure 
pgpreadport iport  Bigloo OpenPGP procedure 
pgpreadfile filename  Bigloo OpenPGP procedure 
These functions read and decode PGP data. OpenPGP allows several keys
to be stored in the same message. Therefore pgpread will
return keys always in a list (even if the message only contains one
key).
The return value is either a list of PGPcompositions (PGPKeys), or a
single PGPcomposition.

pgpwritestring composition [:format 'armored]  Bigloo OpenPGP procedure 
pgpwriteport oport composition [:format 'armored]  Bigloo OpenPGP procedure 
pgpwritefile filename composition [:format 'armored]  Bigloo OpenPGP procedure 
The counterpart of pgpread . These functions encode
PGPcompositions. By default the result is armored (i.e. encoded with
ASCII characters). If the optional :format parameter is
different than the symbol armored , then the composition is
encoded in binary.
Note that there is no means to encode a list of PGPkeys.

pgpencrypt msgstring keys passwords [:hashalgo 'sha1] [:symmetricalgo 'cast5]  Bigloo OpenPGP procedure 
Encrypts the given string. The returned composition can be decrypted
by the owners of the keys, or with one of the passwords.
In the following example Alice and Bob may use their private key to
decrypt the secret message. Users knowing the one of the passwords
(``foo'' and ``bar'') will also be able to decrypt the message.
(pgpwritefile "encrypted.pgp"
(pgpencrypt "my secret message"
(list alicekey bobkey)
'("foo" "bar")))

The given keys should be subkeys of a PGPkey, but if a PGPkey is
given Bigloo will do its best to pick the correct subkey for
encryption.
 If only one subkey exists (the mainkey) then this subkey is
used.
 If two subkeys exist, and the nonmain key is suitable for
encryption, then the nonmain key is used.
 If only one of many subkeys (including the mainkey) is suitable
for encryption, then this subkey is used.
 Else Bigloo raises an error.

pgppasswordencrypt msgstring password [:hashalgo 'sha1] [:symmetricalgo 'cast5] [:mdc #t]  Bigloo OpenPGP procedure 
Deprecated.
Encrypts msgstring with the given password. The returned
PGPcomposition does not contain any information which hashalgorithm
and symmetric encryption algorithm has been used. RFC 4880 specifies
that IDEA and MD5 should be used. However GnuPG uses SHA1 and
CAST5. Therefore Bigloo defaults to the latter algorithms.
Even though the usage of this PGP message is deprecated it yields the
smallest encrypted data. It may be of interest when compatibility with
other tools is not a requirement (but why use OpenPGP then).
The optional mdc flag triggers the usage of a modification
detection code. It is more secure against tampering but requires more
space and might not be recognized by old openpgp implementations.

pgpdecrypt encrypted [:passkeyprovider (lambda () #f)] [:passwordprovider (lambda (key) #f)] [:keymanager (lambda (keyid) '())] [:hashalgo 'sha1] [:symmetricalgo 'cast5]  Bigloo OpenPGP procedure 
Decrypts a PGPcomposition that has been generated by
pgpencrypt or by pgppasswordencrypt .
The function returns the decrypted message (a string) or #f if
decryption was not possible.
If the message can be decrypted with a private key, then Bigloo will
call the keymanager and request a list of PGPsubkeys that
match the given keyid.
If a subkey (returned by the keymanager) is not yet decrypted, Bigloo
will invoke the passwordprovider with the subkey, and request
a password to decrypt the private part of the subkey.
If the message can be decrypted with a password Bigloo will then
request a passkey by invoking the passkeyprovider .
The optional arguments hashalgo and symmetricalgo are
only used for messages that have been encrypted with
pgppasswordencrypt .

pgpsign msgstring key passwordprovider [:detachedsignature? #t] [:onepass? #f] [:hashalgo 'sha1]  Bigloo OpenPGP procedure 
Signs msgstring with the given key. Ideally the key should be
a subkey, but if a complete PGPKey is given, Bigloo will use the
mainkey instead. If the mainkey is not suitable for signing, then an
error is raised.
If the private part of the key has not yet been decrypted then Bigloo
will call the passwordprovider (a procedure) with the subkey to get a
password (a string).
The function returns a PGPcomposition.
If the optional detachedsignature? parameter is set to
#f then the msgstring is not included in the returned
composition.
The onepass? and hashalgo parameters are usually left
at its default values.
Example:
(let ((mykey (car (pgpreadfile "mykey.pgp"))))
(pgpwritefile "msg.sig"
(pgpsign "my signed message"
mykey
(lambda (key) "mypassword")
:detachedsignature? #f)))


pgpverify signature keymanager [:msg #f]  Bigloo OpenPGP procedure 
Verifies a signature.
The keymanager is a function that takes a substring identifier and
returns a list of keys matching this id. Since a signature composition
may contain several signatures this function may be invoked several
times.
The result is a list of subkeys that signed the message. If the
keymanager doesn't have any of the signaturekeys then the result is
the empty list.
A message (string) needs only be given if the signature is
detached. Otherwise the original message is encoded in the
signaturecomposition.
Example:
(let ((sig (pgpreadfile "msg.sig")))
(let ((signers (pgpverify sig mykeymanager)))
(foreach (lambda (subkey)
(print (subkey>string subkey) " signed the message"))
signers)))


pgpsignaturemessage signature  Bigloo OpenPGP procedure 
Returns the signature's message, or #f if the signature is a
detached signature.

pgpkey? key  Bigloo OpenPGP procedure 
pgpsubkey? key  Bigloo OpenPGP procedure 
Predicates for PGPKey and PGPSubkey.

pgpsubkeys key  Bigloo OpenPGP procedure 
Returns a list of PGPSubkeys of the PGPKey. The first key in the
list is the mainkey. The mainkey is used as default for
signatures.

pgpkey>string key  Bigloo OpenPGP procedure 
pgpsubkey>string key  Bigloo OpenPGP procedure 
Returns a string representation of the key (resp. subkey).
Example outputs:
(pgpkey>string key)
=> John Doe john.doe@gmail.com
=> bd4df3b2ddef790c RSA (Encrypt or Sign)
=> 424610a65032c42e RSA (Encrypt or Sign)
(pgpsubkey>string (car (pgpsubkeys key)))
=> John Doe john.doe@gmail.com
=> bd4df3b2ddef790c RSA (Encrypt or Sign)


pgpkeyid subkey  Bigloo OpenPGP procedure 
pgpkeyfingerprint subkey  Bigloo OpenPGP procedure 
Returns the id (resp. fingerprint) of a subkey.
A subkeyid is a 8character binary string.
A fingerprint is a 20character binary string.

pgpmakekeydb  Bigloo OpenPGP procedure 
pgpaddkeytodb db key  Bigloo OpenPGP procedure 
pgpaddkeystodb db keys  Bigloo OpenPGP procedure 
pgpresolvekey db id  Bigloo OpenPGP procedure 
pgpdbprintkeys db  Bigloo OpenPGP procedure 
A simple keymanager implementation based on lists.

15.3.1.1 Signatures
Unless you already have a gpg key create a new PGP key with gpg. Note
that DSA with a keysize greater than 1024 does not work with
SHA1. SHA224,256,384,512 would work, but are not yet implemented
in Bigloo.
$ gpg genkey
...
pub 1024D/A2DA694E 20100807 [expires: 20100827]
Key fingerprint = DFAF 5894 9003 8640 D45B 6199 07CA 0495 A2DA 694E
uid Bigloo Example
sub 1024g/0B8985E5 20100807 [expires: 20100827]

We export both the public and the private key.
$ gpg a o A8453FAB_Bigloo_Example_User.pkey export A8453FAB
$ gpg a o A8453FAB_Bigloo_Example_User.skey exportsecretkeys A8453FAB

This small program will simply read the key and print a humanreadable
representation.
;; contents of printkey.scm
(module printkey
(library openpgp)
(main mymain))
(define (mymain args)
(let ((publickey (car (pgpreadfile "A2DA694E_Bigloo_Example.pkey")))
(secretkey (car (pgpreadfile "A2DA694E_Bigloo_Example.skey"))))
(display (pgpkey>string publickey))
(display (pgpkey>string secretkey))))

The compilation is straightforward and does not require any special flags:
$ bigloo printkey.scm o printkey
$ ./printkey
Bigloo Example
07ca0495a2da694e DSA (Digital Signature Standard)
5fa4e8c90b8985e5 ElGamal (EncryptOnly)
Bigloo Example
07ca0495a2da694e DSA (Digital Signature Standard)
5fa4e8c90b8985e5 ElGamal (EncryptOnly)

As can be seen, the pgpkey>string routine does not
differentiate between public and private keys. We can also sign a message:
(let ((mykey (car (pgpreadfile "A2DA694E_Bigloo_Example.skey"))))
(pgpwritefile "msg.sig"
(pgpsign (readstring)
mykey
(lambda (key) "<Bigloo Example Password>")
:detachedsignature? #f)))

Signatures from Bigloo follow RFC 4880 and can therefore be verified
by gpg .
$ echo "Gpg can verify Bigloo's signature"  ./sign
$ gpg verify msg.sig
gpg: Signature made Sat 07 Aug 2010 10:12:21 PM CEST using DSA key ID A2DA694E
gpg: Good signature from "Bigloo Example"

Inversely Bigloo can verify pgp 's signature. Here we first
generate a signature with gpg .
$ echo "Bigloo can verify gpg's signatures."  \
gpg o msg_gpg.sig a \
defaultkey "Bigloo Example" \
passphrase <Bigloo Example Password> \
sign
You need a passphrase to unlock the secret key for
user: "Bigloo Example"
1024bit DSA key, ID A2DA694E, created 20100807

The following program reads OpenPGP signatures and verifies them. For
simplicity the key database will only contain one key, but it could
contain any number of keys.
(let ((mykey (car (pgpreadfile "A2DA694E_Bigloo_Example.pkey")))
(sig (pgpreadfile "msg_gpg.sig"))
(db (pgpmakekeydb)))
(pgpaddkeytodb db mykey)
(print "Signature message: " (pgpsignaturemessage sig))
(let ((signers (pgpverify sig (lambda (id) (pgpresolvekey db id)))))
(foreach (lambda (subkey)
(display (pgpsubkey>string subkey)))
signers)))

As expected, the program verifies the correct signature.
$ ./verify
Signature message: Bigloo can verify gpg's signatures.
Bigloo Example
07ca0495a2da694e DSA (Digital Signature Standard)

15.3.1.2 Email Usage
Usage of OpenPGP within mails is described in RFC 3156. Encrypted parts and signatures are encoded with their
separate contenttypes. Signatures are done over a canonicalized
version of the message. They also hash over the contenttype headers. OpenPGP's recette program has an example for a signature from kmail,
that can be succesfully verified with Bigloo.
15.3.1.3 Encryption
OpenPGP allows messages to be encrypted with passwords (in this
context ``passkey'') or public keys. It is also possible to encrypt a
message for more than one recipient. In such a case the data will be
encrypted by a sessionkey which in turn is encrypted separately for
each recipient. Since the sessionkey is not very big (compared to the
data) the size overhead is usually insignificant. Let's start by encrypting a message with a simple passkey.
(let* ((secretdata "My secret data\n")
(composition (pgpencrypt secretdata '() '("My secret passkey"))))
(pgpwritefile "secret.pgp" composition))

As usual the pgp message is compatible with gpg :
$ gpg secret.pgp
gpg: CAST5 encrypted data
Enter passphrase: <My secret passkey>
gpg: encrypted with 1 passphrase
$ cat secret
My secret data

As expected, Bigloo can decrypt password protected files that have
been generated by gpg:
$ echo "A secret message encrypted with gpg."  \
gpg o encrypted.pgp symmetric \
passphrase "secret key"

The Bigloo code to decrypt the message is very simple:
(print (pgpdecrypt (pgpreadfile "encrypted.pgp")
:passkeyprovider (lambda () "secret key"))))

In a similar vein it is possible to use public key encryption.
The following example tests the encryption and decryption part of
Bigloo.
(let* ((mykey (car (pgpreadfile "A2DA694E_Bigloo_Example.skey")))
(db (pgpmakekeydb))
(secretdata "My secret message")
(encrypted (pgpencrypt secretdata `(,mykey) '())))
(pgpaddkeytodb db mykey)
(let* ((keymanager (lambda (id) (pgpresolvekey db id)))
(passwordprovider (lambda (key) <Bigloo Example Password>))
(decrypted (pgpdecrypt encrypted
:keymanager keymanager
:passwordprovider passwordprovider)))
(if (not (string=? decrypted secretdata))
(error "decrypttest"
"Something went horribly wrong"
decrypted))))

Note that a secret secret key has a part that is encrypted by a
password. During decryption Bigloo needs access to this encrypted data
and therefore invokes the passwordprovider so it can decrypt it. In
many cases this will trigger an interactive callback with the
user. Here, in this toy example, we know that the password that is
needed is for the Bigloo Example key. In a more general case the
passwordprovider will have to print the key to give more information
to the user. In the following example we show how to encrypt data for 3 passwords and
one key.
(let* ((mykey (car (pgpreadfile "A2DA694E_Bigloo_Example.skey")))
(db (pgpmakekeydb))
(secretdata "My secret message")
(encrypted (pgpencrypt secretdata `(,mykey)
'("pass1" "pass2" "pass3"))))
(pgpwritefile "multi_receiver.pgp" encrypted))

We believe that gpg has a bug and does not know how to handle
such messages correctly. Bigloo, however, decrypts the message with
any of the possible options.
Bigloo's OpenPGP implementation only exposes few library
functions. As a consequence some features are not accessible. The
keymanagement system is very rough, and there are no means to
inspect messages in more detail. It should be possible to expose or
implement many of those missing features with little effort. The most
timeconsuming part is generally designing a clean API and the
testing/debugging of new features: when something goes wrong it can
take a huge amount of time to find the reason. Developers interested in improving Bigloo's OpenPGP library can print
a huge amount of debugging information by enabling the debugmacro in
util.scm . Bigloo's OpenPGP implementation is not designed for
speed and takes no shortcuts. The debugging output can therefore be
used to follow the specification of RFC 4880 (or 2440).
