Next: openssl SSL/TLS, Previous: openssl CIPHER, Up: SXEmacs OpenSSL API [Contents][Index]
While keys for symmetric ciphers can be easily stored as strings, keys for asymmetric algorithms are more complex. The openssl API therefore provides a dedicated primitive type, called pkey. Pkey objects can contain key pairs – i.e. pairs of public keys and corresponding private keys, public keys, and also certificates. They are general container object for various subtypes such as RSA, DSA, EC, and DH keys.
However, you cannot directly create such a pkey object nor access nor modify parts of it. Pkey objects are actually meant as transporter objects to simplify those functions which need them.
Return t
if object is a pkey, nil
otherwise.
Return the size a public key pkey in bits.
Return non-nil
if pkey contains private data.
Note: This function is not native OpenSSL.
Return a copy of pkey stripped by the private data.
Note: This function is not native OpenSSL.
The above functions have a generic character because they are
independent from the choice of algorithm, see below. For each of
these algorithms we provide a constructor function
ossl-algo-generate-key
and a subtype predicate, named
ossl-algo-pkey-p
. In case of RSA and DSA we also support
a subkey check.
Note: At the moment we do not provide the creation of DH-keys.
Now the first important asymmetric algorithm is RSA. As mentioned in
the general introduction OpenSSL can be built without it. The
following functions therefore exist iff (featurep 'openssl-rsa)
evaluates to t
.
Return an RSA public key with of length bits and exponent exp.
Return t
iff pkey is of RSA type.
Return t
if pkey1 is a subkey of pkey2, nil
otherwise, i.e. if pkey1 has the same public key data as
pkey2 and pkey2 has all private data.
Note: This function is not native OpenSSL.
(setq rsaexmpl (ossl-rsa-generate-key 2048 3)) ⇒ #<OpenSSL RSA private/public key, size 2048> (ossl-rsa-pkey-p rsaexmpl) ⇒ t (ossl-pkey-private-p rsaexmpl) ⇒ t
(setq rsapub (ossl-pkey-get-public rsaexmpl)) ⇒ #<OpenSSL RSA public key, size 2048> (ossl-pkey-private-p rsapub) ⇒ nil (ossl-rsa-subkey-p rsapub rsaexmpl) ⇒ t
Another important asymmetric algorithm is DSA. The presence of DSA
support in the underlying library can be checked by (featurep
'openssl-dsa)
. Nonetheless, it is very unlikely to face an OpenSSL
installation without DSA or RSA.
Return a DSA public key with of length bits seeded with (optional) seed.
Return t
if pkey is of DSA type, nil
otherwise.
Return t
if pkey1 is a subkey of pkey2, nil
otherwise, i.e. if pkey1 has the same public key data as
pkey2 and pkey2 has all private data.
Note: This function is not native OpenSSL.
(setq dsaexmpl (ossl-dsa-generate-key 1024)) ⇒ #<OpenSSL DSA private/public key, size 384> (ossl-dsa-pkey-p dsaexmpl) ⇒ t (ossl-pkey-private-p dsaexmpl) ⇒ t
(setq dsapub (ossl-pkey-get-public dsaexmpl)) ⇒ #<OpenSSL DSA public key, size 384> (ossl-pkey-private-p dsapub) ⇒ nil (ossl-dsa-subkey-p dsapub dsaexmpl) ⇒ t
Elliptic curve cryptography is quite new and is possibly missing on
many systems. Use (featurep 'openssl-ec)
to check for elliptic
curve support. Another particularity of the ec system is that it is
based on a fixed set of curves which can be referred to by name. At
the moment we do not support creating custom curves.
Return a list of builtin elliptic curves.
Return a EC public key on curve.
curve may be any symbol from (ossl-ec-available-curves)
.
Note: At the moment we do not support creating custom curves.
Return t
if pkey is of EC type, nil
otherwise.
(ossl-ec-available-curves) ⇒ (Oakley-EC2N-4 Oakley-EC2N-3 wap-wsg-idm-ecid-wtls12 wap-wsg-idm-ecid-wtls11 wap-wsg-idm-ecid-wtls10 wap-wsg-idm-ecid-wtls9 wap-wsg-idm-ecid-wtls8 wap-wsg-idm-ecid-wtls7 wap-wsg-idm-ecid-wtls6 wap-wsg-idm-ecid-wtls5 wap-wsg-idm-ecid-wtls4 wap-wsg-idm-ecid-wtls3 wap-wsg-idm-ecid-wtls1 c2tnb431r1 c2pnb368w1 c2tnb359v1 c2pnb304w1 c2pnb272w1 c2tnb239v3 c2tnb239v2 c2tnb239v1 c2pnb208w1 c2tnb191v3 c2tnb191v2 c2tnb191v1 c2pnb176v1 c2pnb163v3 c2pnb163v2 c2pnb163v1 sect571r1 sect571k1 sect409r1 sect409k1 sect283r1 sect283k1 sect239k1 sect233r1 sect233k1 sect193r2 sect193r1 sect163r2 sect163r1 sect163k1 sect131r2 sect131r1 sect113r2 sect113r1 prime256v1 prime239v3 prime239v2 prime239v1 prime192v3 prime192v2 prime192v1 secp521r1 secp384r1 secp256k1 secp224r1 secp224k1 secp192k1 secp160r2 secp160r1 secp160k1 secp128r2 secp128r1 secp112r2 secp112r1)
(setq ecexmpl (ossl-ec-generate-key 'secp224r1)) ⇒ #<OpenSSL EC private/public key, size 512> (ossl-ec-pkey-p ecexmpl) => t (ossl-pkey-private-p ecexmpl) ⇒ t
(setq ecpub (ossl-pkey-get-public ecexmpl)) ⇒ #<OpenSSL EC public key, size 512> (ossl-pkey-private-p ecpub) ⇒ nil
Finally, there is the DH key exchange. Its presence can be checked
by (featurep 'openssl-dh)
. At the moment we do not provide
constructor functions.
Return t
if pkey is of DH type, nil
otherwise.
Once you have a pkey object you can use it for encryption/decryption, and/or signing/verification. Talking in OpenSSL hybrid encryption and decryption is referred to as sealing and opening, respectively.
Return an envelope derived from encrypting string by cipher under pkey with the hybrid technique.
That is, create a random key/iv pair for the symmetric encryption with cipher and encrypt that key/iv asymmetrically with the provided public key.
The envelope returned is a list
(encrypted_string encrypted_key encrypted_iv)
where
encrypted_string is the (symmetrically) encrypted message
encrypted_key is the (asymmetrically) encrypted random key
encrypted_iv is the (asymmetrically) encrypted random iv
Note: You probably want to put a wrapping encoder function
(like base16-encode-string
) around it, since this function
returns binary string data.
Return the deciphered message string from an envelope obtained
by ossl-seal
.
ossl-seal
)
In the following example we reuse the keys generated above.
(let ((envl (ossl-seal 'AES-256-CBC "I do not want to tell" rsaexmpl))) (setq str (car envl) key (nth 1 envl) iv (nth 2 envl)) (mapcar #'base16-encode-string envl)) ⇒ ("0e6a38b28efea3ca4901b268c141d7ac23ed5f8fa598d23d9846fe3ec1 47278e" "167911a73b0a228b24e78bdd37197ec95b21bed3bbd62d1915d8fac791 7915fd49fdd9774e7906ca53ed3bf4fb20de8339e628d469a496f7351c 06fddda49b71c90e73e31c406cfb0f0fb7411d1c9d49842603c45415cc 3a8f660c728e8f05c6479d004f5068a7969294b4cc81e13dd257df37dc 886b11266a3ccba576396d200ebb1a3e8f7185fdbc6de40b63964562f9 1cbe39118a07415c030fd4c3e25bbe2a64b2ab635b2ef9a71a5ddeeaf0 4a73d7cd04ad334d1de04228db5a9fb9aebfa6a9dc9d76af5ec329b360 d1cd8da45868450a3bc5c41bba95a0ad74439f7d5edffcdf7dff09c296 35ae13215be1ae55f5d2b5e97d6a4d523470eef050b07193" "ab458ccb46cbc092c31614e997cd176b")
(ossl-open 'AES-256-CBC str rsaexmpl key iv) ⇒ "I do not want to tell"
The above example is nice but does not demonstrate the real power of
hybrid encryption. In the following example we reuse the public
subkey rsapub
of rsaexmpl
from above. Also you will
notice that the random key/iv pair has changed and thus the resulting
encrypted string is not the same.
(let ((envl (ossl-seal 'AES-256-CBC "I do not want to tell" rsapub))) (setq str (car envl) key (nth 1 envl) iv (nth 2 envl)) (mapcar #'base16-encode-string envl)) ⇒ ("93a5b3f2eb5a2eaee44805150717bb325b4e90be947591cc46b7819d3f 4ec284" "300b9ab5a79524fdcb40fbed6bae7e9c470baa0d230f9b97c9b35de442 62f82b626ef7668329d34cffc3eeddf535a879e974825e984c7e045c0a 526b3b58453ae55926af519400f32c4aee7115088068fcb6fc75ce78c5 b6d61bbaf90f0c4aff1d83efd63c45c62989c29efda187bcbd94edf9f1 427ec8dce22cd6333e8196120285dc5bb224b9d7e9ecfb23e016475706 5da6f999560d010adaf0465b108b2a84989ff8bd17778b61875f633a35 a02c2cc1fdf3a3e50ad4a5fb7ad9a05b1a3a1818a21f3d7c71a33949f6 437ee64bee60e1ae92ebea43ca524b15344a7fc2712e9758b98f1b2c9d c8ad3d074486f0d35fece7bf7b6ce979fa760aa7bd5854b2" "6979d574e8bc10dfddefd4cb017186a2")
(ossl-open 'AES-256-CBC str rsaexmpl key iv) ⇒ "I do not want to tell"
;; try with just the public part
(ossl-open 'AES-256-CBC str rsapub key iv)
error→ cannot open, key has no private key data
Also note you cannot use DSA keys for sealing. They are exclusively for signatures.
Signing and verifying works similar to sealing and opening. Instead of a cipher algorithm you need to specify a message digest algorithm. However, in this case the signature step requires a pkey with private data and the verification step can be done with only the public part of the key.
Return a signature obtained by signing string under digest with pkey.
That is, hash the message string with the message digest digest and encrypt the result with the private key pkey.
Note: Due to some relationship between the public key system and the message digest you cannot use every digest algorithm with every private key type. The most certain results will be achieved using RSA keys with RSA-* digests, DSA keys with DSA-* digests.
See ossl-available-digests
.
Note: You probably want to put a wrapping encoder function
(like base16-encode-string
) around it, since this returns
binary string data.
Return t
iff sig is a valid signature of string
under digest obtained by pkey.
That is, hash the message string with the message digest
digest, then decrypt the signature sig with the public key
pkey. Compare the results and return t
iff both hashes
are equal.
ossl-sign
)
Again we reuse the keys defined above.
(progn (setq sig (ossl-sign 'SHA1 "I owe you a beer" dsaexmpl)) (base16-encode-string sig)) ⇒ "302d021500c2e5197d266573216e4daa85e0a7e43424d0f031021451186 24043517e0cd24f381d0e6c92f96198f297"
(ossl-verify 'SHA1 "I owe you a beer" sig dsapub) ⇒ t
;; we try to fake the signed text
(ossl-verify 'SHA1 "I owe you 10 beer" sig dsapub)
⇒ nil
Note that you cannot use all combinations of pkey and digest
algorithm. Suitable digests can be found in the
(ossl-available-digests)
list. Given a digest dgst there
must be an entry RSA-dgst
in order to use an RSA key for
signatures under dgst. Respectively there must be an entry
DSA-dgst
for DSA key pairs and all DSA-suitable digests can
also be used for EC keys.
In order to persistently store generated keys the openssl API provides a simple interface to the PEM routines. PEM is the format for key pairs or public keys.
Return a key (the public part) stored in a PEM structure from file.
Return a key stored in a PEM structure from file. If the (private part of the) key is protected with a password provide (optional) password.
Write pkey (the public part) in a PEM structure to file.
Write pkey in a PEM structure to file. The key itself is protected by (optional) cipher with password.
cipher can be set to nil
and the key will not be
encrypted. password is ignored in this case.
Return pkey as PEM encoded string.
Return pkey as PEM encoded string. The key itself is protected by (optional) cipher with password.
cipher can be set to nil
and the key will not be
encrypted. password is ignored in this case.
(ossl-pem-write-key "/tmp/mykey.pem" dsaexmpl)
(let ((stored (ossl-pem-read-key "/tmp/mykey.pem"))) (ossl-verify 'SHA1 "I owe you a beer" sig stored)) ⇒ t
(ossl-pem-public-key rsapub) ⇒ "-----BEGIN PUBLIC KEY----- MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAtGE7JaGUsVIfLUJmzlkR qfB7CJjFlYU7tGmD7C1rBiGz0sjTlPwsMjwwCLP6byRvebVeDxGrxbeyZE3sSB4q oVbevhbwwBMY5+j/8q+3l7KbqoP9CGG40ZbEC6IOqFn8kOmliPdWUlogI1Gr4b7U R4F+TM6m3r3AQoxeqq+rR5kHat2mvBpxm0o8FZ2KW6ZCAkAXoA3NNCXtSUF9zA6A u3acUP4eiFAkS4Q6hIuZli4PzxvUugB5/ekyaa5cRzIEqIhh90mkpqjM9qpR15hk 39qiM/SxXmLlncU534byldSgnoIse3tnia4WRBm2qK3zTr24zaBtTTXfmRJMWQwZ ewIBAw== -----END PUBLIC KEY----- "
(ossl-pem-public-key rsaexmpl) ⇒ "-----BEGIN PUBLIC KEY----- MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAtGE7JaGUsVIfLUJmzlkR qfB7CJjFlYU7tGmD7C1rBiGz0sjTlPwsMjwwCLP6byRvebVeDxGrxbeyZE3sSB4q oVbevhbwwBMY5+j/8q+3l7KbqoP9CGG40ZbEC6IOqFn8kOmliPdWUlogI1Gr4b7U R4F+TM6m3r3AQoxeqq+rR5kHat2mvBpxm0o8FZ2KW6ZCAkAXoA3NNCXtSUF9zA6A u3acUP4eiFAkS4Q6hIuZli4PzxvUugB5/ekyaa5cRzIEqIhh90mkpqjM9qpR15hk 39qiM/SxXmLlncU534byldSgnoIse3tnia4WRBm2qK3zTr24zaBtTTXfmRJMWQwZ ewIBAw== -----END PUBLIC KEY----- "
(ossl-pem-key rsaexmpl 'AES-256-CBC "foobar") ⇒ "-----BEGIN ENCRYPTED PRIVATE KEY----- MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIk4VVj28lKIgCAggA MB0GCWCGSAFlAwQBKgQQ0uzDwfFB2m5ZUCt8K1YSvwSCBNCcQuY1S1c7Blsm7QlH iHji7xWcigj6U7U6IQ0y/a6+U/ku2/IQc4I/sjsYNj1ZKBjkHxuWqVtGvKD/AB/r 2XFYkOpg7X2SvpVXuCkHk/B7l8ifQViqwu3k8r+8jHmLuxa21xysrTLOef8LmCkg ePaOArDKascJngpkUtMM269owh1ZBUSmKqQqR+jnpXw+dummdlr2tA0t3Bl+899q e6L7sZ330XRTnzyQUuZvBpV8bV0AlaI3jlPROu56MKiUiDU0n9lvzYegWGAJjOvS qYW3FPY/B7MczXCFQOmg3XWXWJ/2szRQnWvuM5imhwVF4YbPO30H6KG2sRc5u4Bs vym71CdlD77+YEw2dQ36bgjLE2v9aFIuuqqRlbNO1wUo1D0JFrN0ivGnliA6tCQ2 tADHeEqKeXjCk4GM+rZB9d/kx2RqTgqu+JolaO1+8lxWRMT+aLj5EPN8zHOaRhDL 3farG89PEOUvPRzkn+18laPBJ0o9AvwYC9Bmi072Lq7XtOIH0iELxY2RyQD0PLD2 cLdt5tkQDfuUhrUJuhh3waMDa7qe9lMGnxsmlapZn5FY1kZ6gBO79BBu9sFmsr1x IRDT5PJc2V+BU9fn3Vu6WM3P56x7WfUjycqpvmu7yshW8D/8KRNYbeBIAXuRKCoJ dRIp/c+UWSPDVb68NikRvTRvj0vVrGMsesRkl89uL6liGarGghEV9lwNDQB5XN0q wZ+4LXP4DZQlBK3g9Bq7rL6F3ZuxGdThjQO6IAve6MltfOIN/x/schcoE41g2y0D 0hn8vnDkGwWKFE59qOZ7/iQOOKJisF6MjxnkhlcTvG3ev2mrSsJHdiIoN9u8Zm6o Xca/k7JEs3rkr5MhrjxpGznq6Z5skEWEFFGD5XlXKYsHlP5YDxVXLED1cQHKcydC t2uPsB/Uqj4zl/lBc0/asQ8gyZiR2Fc5DHjUkmQ/5kH4LulvVLJgCC8JRs2AutBu DsqfvEj8uhmCuNYlsrOGrrOo/m2HPQ1DeoJcoL+H8KQG1WjPo0bnaV0Xlf6o+IkI G42pDGVeNSZDc+gqbXTzHDF0snOVDO7nfJ+kWmTFpHhI8Ht5H6SaaAIcgIQcWZgZ vA7e54XQ6HBUARFaPdw8kXyilu3lGunacjfipCdsOaF3WxGgdPmQTfuQOqglYhlc v/WPjyV9WgpEaJKM2Vcwb+CiOeteKnqp9ZLdmb4fZJNP2oIlKLtQSHsmdFGEr7BP 7hxoi/kcD9QpuC9CHn1rZC99ZwWBa+UmK5s+P8LJRfi6a8qhR3gA6H/JGZLFiW0C Vrmir9u33UkroKfn+JTuMZV5e+U7YNFSJhX95nbLTIx44ItyztGlE5+lHMPA+N/p +OQM2F0kzfSZ2F1M3x3iO4VPzfEC6vNBpOOhhssSoL9ThNYlCQOVa+QemEjmVuEs PLluotrTI3Cetk4nanvj4HGb6KjnkU1JdQ6iKSEl2JnYWrmNNoB3N06/h/7DQpiy p/tevEVZQxK2cOklJrgcuNtVXe3c/9OVRKDuu3m1GstbQ4pcqijc55kuEtA0tmvn S5WFFj4/cVucd2K3IOHCttEfgDwVNDDzG2shBsKT1JDY4aDOBD3xe+ggstVkGmRL ocNNE7QyxF/GOgW9iTQr/yOp9A== -----END ENCRYPTED PRIVATE KEY----- "
Next: openssl SSL/TLS, Previous: openssl CIPHER, Up: SXEmacs OpenSSL API [Contents][Index]