cryptoIDlib version 0.3.3 September 16, 2004 Trevor Perrin http://trevp.net/cryptoID/ ============================================================================ Introduction ============= cryptoIDlib is a python library and command-line tools for working with cryptoID certificate chains [0]. Among other things, it provides client and server implementations of the cryptoID key management protocols [1]. cryptoIDlib's sister library is TLS Lite [6]. TLS Lite is necessary if you want to use the key management protocols. Also, if you have TLS Lite and cryptoIDlib, you can use cryptoIDs to authenticate in TLS. If you have questions or feedback, feel free to contact me. License/Acknowledgements ========================= All code here is public domain. Thanks to Edward Loper for Epydoc, which generated the API docs. Installation ============= Requirements: - Python 2.3.2 or higher Options: - If you have the M2Crypto interface to OpenSSL, this will be used for fast RSA operations. - If you have the cryptlib_py [4] interface to cryptlib [5], this will be used for good randomness generation. If cryptoIDlib can't find an OS- level random-number generator (i.e. /dev/urandom on UNIX or CryptoAPI on Windows), then you must MUST install cryptlib. - The tlslite package [6] is necessary to use the key management protocols. It will also allow you to use cryptoIDs within TLS. - If you have pycrypto [7], this will be used for fast RSA operations. - If you have the GMPY [8] interface to GMP, this will be used for fast RSA operations. - These packages don't need to be present at installation - you can install them any time, and cryptoIDlib will detect them. - If you have OpenSSL, you can adjust the setup.py file to build a version of the 'scanmods' shared library which uses OpenSSL's SHA-1 routines for 20% faster modifier scanning. On Windows: - Run the installer in the 'installers' directory. *OR* - Run 'setup.py install' (this only works if your system has a compiler available). Anywhere else: - Run 'setup.py install' Test Command-Line Tool: - The 'cryptoID.py' script should have been copied into the 'Scripts' subdirectory of your python directory, and made executable. - From the distribution's test subdirectory, run 'cryptoID.py test .' (WARNING: Be careful running this (or any) script from the distribution's root directory. Depending on your path, the scripts may load the local copy of the library instead of the installed version, with unpredictable results). Test Library: - Start the python interpreter (preferably while *outside* the distribution's root directory, to make sure it's using the installed version of the library). - Run 'from cryptoIDlib.api import *' - Run 'SelfTest().selfTest()' Getting Started with the Command-Line Tools ============================================ CryptoIDlib comes with three command-line scripts: cryptoID.py, cryptoIDcli.py, and cryptoIDsrv.py. They can be run with no arguments to see a list of commands. cryptoID.py ------------ This script is used for basic operations like generating keys, and creating, validating, and signing certChains. To create a new cryptoID and certChain, you start by generating keys for use in the : cryptoID.py genkey rsa 2048 > keyA cryptoID.py genkey rsa 2048 > keyB Then you create a new containing a by specifying the security level and a key expression for the : cryptoID.py newcert "(a and b)" keyA keyB mod=112 > chain0.xml You can find modifiers that give higher security levels by trying: cryptoID.py scanmods chain0.xml 112 0 1000000 You can create additional keys and add additional s: cryptoID.py genkey rsa 1024 > keyC cryptoID.py addcert chain0.xml "a" keyC urn:ietf:smime > chain1.xml Some things to note: - Lowercase variables used when creating a new key expression are only place-holders, and will be converted to the appropriate uppercase variable. - After listing all the key files for the key expression, you can list protocols that will be used in the cert. To add signatures to a , you just specify the certChain file, the key file, and the number of minutes until signature expiration, and the library will figure out what type of signature to apply: cryptoID.py addsig chain1.xml keyA 10080 > chain2.xml cryptoID.py addsig chain2.xml keyB 720 > chain3.xml Validating a is easy: cryptoID.py valid chain3.xml cryptoIDcli.py --------------- This script is used for accessing key management servers. It can only be used if TLS Lite is installed. Reading [1] is recommended to understand how cryptoID key management works. Before using a key management server with a particular certificate, there are two steps a client needs to perform: - regUser: the client authenticates the server based on its cryptoID, and stores a username and SRP password verifier into the server's verifier database. The client can also register a "subordinate" password that's only used for certifying subkeys, not for configuring the servers: cryptoIDcli.py regUser https://localhost e45yh.nfqvm.j7obw.g3tp9 alice pAsWd sUbpAsWd - getKey: the client retrieves the server's public signing key. The client can then issue a certificate to this key to enable CA or VA services. The client can authenticate the server *either* by its cryptoID, or with SRP: cryptoIDcli.py getkey https://localhost alice pAsWd > keyCA Clients can use key management servers to make their cryptoID certChain accessible from different devices. The client uses 'regCert' and 'putChain' to store a certChain at a server. This certChain must certify the server's signing key. The client can then use 'getChain' to retrieve the certChain. The client then adds a new cert to the chain, and uses 'getSigs' to get the CA's signature on the new cert. For example, below a client creates a cryptoID and root cert. The client then adds an additional cert containing a CA server's key. Note that instead of specifying the server's key file, the client can specify the server directly, and the 'addcert' command will use the getKey protocol to retrieve the key. The client then registers this new cert with the CA, signs it, and posts the chain to the CA server. cryptoID.py newcert "a" keyA mod=112 > chain0.xml cryptoID.py addcert chain0.xml "a" https://localhost,alice,pAsWd > chain1.xml cryptoIDcli.py regcert https://localhost alice pAsWd chain1.xml 1 720 CA cryptoID.py addsig chain1.xml keyA 720 > chain2.xml cryptoIDcli.py putchain https://localhost alice pAsWd chain2.xml Now the client can generate a key on another machine, and get it certified under his cryptoID: cryptoIDcli.py getchain https://localhost alice sUbpAsWd > chain3.xml cryptoID.py genkey rsa 1024 > keyNew cryptoID.py addcert chain3.xml "a" keyNew 90 > chain4.xml cryptoID.cli.py getsigs https://localhost alice sUbpAsWd chain4.xml > chain5.xml Clients can also use key management servers to make their keys revokable. The client generates a certificate containing a server's signing key, and registers this certificate with a VA server. The VA will then issue validation signatures to this certificate until the certificate is revoked by the same user who registered it. For example, below a client retrieves a server's signing key, and uses it to create a cryptoID root certificate. He then registers the rootCert with the VA, and instructs the VA to issue validation signatures with a lifetime of 12 hours. cryptoIDcli.py getkey https://localhost alice pAsWd > keyVA cryptoID.py addroot 112 "(a and b)" keyA keyVA > chain0.xml cryptoIDcli.py regcert https://localhost alice pAsWd chain0.xml 0 720 VA > chain1.xml The output of 'regCert' is the same certChain, but with an "annotation" added that lists the VA's URL and cryptoID. An annotated certChain essentially knows how to validate itself. So to retrieve the latest validation signatures, the client just does: cryptoIDcli.py getvasigs chain1.xml > chain2.xml The user might store chain1.xml permanently, and issue the above command every morning when he arrives at work. If he suspects keyA has been compromised, he can revoke the certificate (and in this case the entire cryptoID) by issuing: cryptoIDcli.py revcert https://localhost alice pAsWd chain1.xml 0 The VA will refuse to issue further validation signatures, so the compromised key will quickly become worthless. cryptoIDsrv.py --------------- This script is used for running a key management server. It can only be used if TLS Lite is installed. This server should be considered a prototype - it's slow, flimsy, and probably vulnerable to attacks. When you start a server, you point it at a directory, and it will create the various keys and databases that it needs: - a signing key that it uses for issuing signatures - a cryptoID key that it uses for authenticating itself - a cryptoID certificate chain that it uses for authenticating itself - a database of SRP verifiers it uses to authenticate clients - a database containing certID registrations - a database containing certificate chains Creating a cryptoID may take a minute or two (it creates a 120-bit cryptoID; this takes an average of 13 seconds on a Pentium 4 1.7Ghz). Later on you can restart the server in the same directory and it will pick up where it left off. To run a key management server, listening on port 443, in the current directory: cryptoIDsrv.py localhost Getting Started with the Library ================================= Run 'from cryptoIDlib.api import *' to import all the top-level objects. You can use help() on these objects for more details. The most important classes are: CertChain Client Server To create a new cryptoID and certChain, you start by generating keys for use in the : keyA = generateRSAKey(2048) keyB = generateRSAKey(2048) Then you create a new containing a root by specifying the security level and a key expression: chain = CertChain() chain.addCert("(a and b)", [keyA, keyB], secLevel=112) You can view the chain with: print chain.write() You can find modifiers that give higher security levels by trying: chain.scanModifiers() You can create additional keys and add additional s: keyC = generateRSAKey(1024) chain.addCert("a", [keyC], None, ["urn:ietf:smime"]) To add signatures to a , you can just pass in the key, and the library will figure out what type of signature to apply: chain.addSignature(keyA, notAfter = getHoursFromNow(168)) chain.addSignature(keyB, notAfter = getHoursFromNow(12)) You can parse a string: chain2 = CertChain() chain2.parse(chain.write()) Validating a is easy: chain.validate() To access a key management server, you instantiate a client class and then call methods on it. For example, to get a certChain from a CA server, do: client = Client("https://localhost", "alice", "sUbpAsWd") chain = client.getCertChain("a", keyNew) To revoke the cert at index 2 from a certChain, do: client = Client("https://localhost", "alice", "pAsWd") client.revokeCert(chain, 2) History ======== 0.3.3 - 9/16/2004 - os.urandom() support - Fixed win32prng on some systems 0.3.2 - 9/12/2004 - Minor bugfix: when cryptlib_py and and cryptoIDlib present, cryptlib was complaining about being initialized twice 0.3.1 - 5/23/2004 - removed cryptoID_URL - changed CA signatures-per-key-expression rule - allowed to float 0.3.0 - 3/20/2004 - updated to work with tlslite 0.3.0 - added some API docs via epydoc - removed unhandled exception catching around public functions 0.2.3 - 3/04/2004 - pycrypto and GMPY support 0.2.2 - 2/29/2004 - removed signature/listVABadKeys and signature/nonce 0.2.1 - 2/26/2004 - redid key management protocols yet again - added better PRNG support (/dev/random, CryptoAPI, or cryptlib) 0.2.0 - 2/19/2004 - redid key management protocols again, based on document - doesn't require tlslite to load 0.1.9 - 02/16/2004 - redid key management protocols - integrated with tls_lite - changed most exceptions to builtins 0.1.8 - 02/09/2004 - updated utils based on tls_lite changes 0.1.7 - 02/01/2004 - reorg'd code (breaking jython) to facilitate reuse with tls_lite - changed exceptions to use built-ins - added some accessors for the benefit of tls_lite - removed 'chaff' from - changed hashing to include padding 0.1.6 - 01/16/2004, updated python support for VA protocols 0.1.5 - 12/13/2003, added python support for VA protocols 0.1.4 - 12/09/2003, added to 0.1.3 - 12/01/2003, added certID 0.1.2 - 11/23/2003, java port, other fixes and enhancements 0.1.1 - 10/30/2003, bugfix in setup.py, added 'chaff' to 0.1.0 - 10/13/2003, first release References =========== [0] http://trevp.net/cryptoID/ [1] http://trevp.net/cryptoID/cryptoID2.pdf [2] http://sandbox.rulemaker.net/ngps/m2/ [3] http://www.openssl.org [4] http://trevp.net [5] http://www.cs.auckland.ac.nz/~pgut001/cryptlib/ [6] http://trevp.net/tlslite [7] http://www.amk.ca/python/code/crypto.html [8] http://gmpy.sourceforge.net/