Bigloo's implementation of RSA is based on RFC 3447, PKCS #1 v2.1. It does
not feature multiprime RSA, though.
secure against timing attacks. Furthermore
some error codes might reveal information to attackers.
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.
RSA-Key | Bigloo Cryptography class |
Complete-RSA-Key | Bigloo Cryptography class |
(class Rsa-Key modulus::bignum exponent::bignum)
(final-class Complete-Rsa-Key::Rsa-Key
;; for the complete-rsa-key "exponent" takes the role of 'd'
e::bignum p::bignum q::bignum
exp1::bignum ;; d mod (p-1)
exp2::bignum ;; d mod (q-1)
coeff::bignum) ;; (inverse of q) mod p
|
|
RSA keys can be read and written using
read-pem-key
and
write-pem-key
(
PEM).
generate-rsa-key [:key 1024] [:show-trace] | 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:
extract-public-rsa-key complete-key | Bigloo Cryptography procedure |
Returns the public partial key of the given complete key.
This procedure is implemented as follows:
(define (extract-public-rsa-key::Rsa-Key key::Complete-Rsa-Key)
(with-access::Complete-Rsa-Key key (modulus e)
(make-Rsa-Key modulus e)))
|
|
extract-private-rsa-key complete-key | Bigloo Cryptography procedure |
Returns the private partial key of the given complete key.
|
rsa-key=? 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.
|
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 rsa-example (library crypto))
|
Now read the key:
(define *key* (read-pem-key "my_rsa_key.pem"))
(define *public-key* (extract-public-rsa-key *key*))
|
The public portion of the key can be distributed:
;; publish the *public-key*:
(write-pem-key-string *public-key*)
|
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 msg-hash (sha1sum "my message"))
(define msg-hash-bignum (octet-string->bignum msg-hash))
|
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
octet-string->bignum
function:
(define msg-hash-bignum (octet-string->bignum (string-hex-intern msg-hash)))
|
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 (rsa-sign *key* msg-hash-bignum))
|
The signature is again in bignum form. If needed there are several ways to transform
it into string-form (for instance
bignum->string
or
bignum->octet-string
).
The signature can now be distributed. Anyone wanting to verify the signature
simply has to create the same message-hash and call
rsa-verify
with our
public key:
(rsa-verify *public-key* msg-hash-bignum 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 encrypted-key (rsa-encrypt *public-key* (octet-string->bignum "my random password")))
|
Alice simply sends us the
encrypted-key
. On our side we can now
decrypt the key:
(define aes-key (bignum->octet-string (rsa-decrypt *key* encrypted-key)))
|
We can now decrypt the previously received message:
(decrypt 'aes aes-key encrypted) => "Cryptography"
|