# Perl script to generate your own CA and some certificates. # Platform Windows2000pro-sp3, tomcat 4.1.27, internet explorer 6, openssel.0.9.7b. # # I created this, from some articles and manuals, I found on the net. # I copied a lot from this document:: http://217.31.71.131/howtoon-certificates.html, # and I plan to looke more the email with subject 'OpenSSLers for Social Responsibility?' # by Charles B Cranston . # # I still don't know, if the certificates works, with my setup, but I will test it in the # days to follow. # # Currently I am using the same configfile (openssl.cnf), for all invocations of the openssl # tool. But I can see in the email by CBC, that it is propably a good idea, to create # severeal different configfiles, depending on, what kind of operation, you want # to perform, with the openssl tool. # # I apologice, if you think this email is a spam mail - I am still learning pki/ssl/x509. # If it contains a lot of errors, then I hope that everybody on the list (at least the # new ones, like myself), will learn more, if and when somebody points out the bugs/mistakes. # # Best Regards # Stefan Krabbe - 20030826 # email: dsl109249@vip.cybercity.dk # # Here follows the Perl script. use strict; my $openssl = 'e:/openssl/out/openssl.exe'; my $debug = 0; my $ca = 'e:/certs/ca'; #Create the demoCA, the directory in which to do the signing. mkdir($ca); mkdir($ca.'/demoCA'); mkdir($ca.'/demoCA/newcerts'); # dir containing new certificates) mkdir($ca.'/demoCA/certs'); # certificates mkdir($ca.'/demoCA/crl'); # revocation list mkdir($ca.'/demoCA/private'); # contains the CA's private key if not given on cmd-line system('echo 01 > '.$ca.'/demoCA/serial'); # text file which contains "01" only at first, certs serial number system('touch '.$ca.'/demoCA/index.txt'); # empty text file at first, contains index of certs # $ca.'/demoCA/cacert.pem' # contains the CA's certificate if not given on cmd-line #Create a private key for the root CA, which we will name/call 'sktestca'. mkdir('e:/certs/key'); system($openssl.' genrsa -out e:/certs/key/sktestca.key -des3 1024'); #Display contents of key if($debug) { system($openssl.' rsa -noout -text -in e:/certs/key/sktestca.key'); } #Derive the RSA public key system($openssl.' rsa -pubout -in e:/certs/key/sktestca.key -out e:/certs/key/sktestca_public.key'); #Create a self-signed certificate for the sktestca root CA. mkdir('e:/certs/crt'); system($openssl.' req -new -key e:/certs/key/sktestca.key -x509 -days 365 -out e:/certs/crt/sktestca.crt -config e:/certs/openssl.cnf'); #This creates an x509 self-signed certificate (signed using the sktestca.key private key), valid for 365 days, #in PEM format #Make the above created PEM certificate available through the webserver! #Create a DER equivalent: system($openssl.' x509 -inform PEM -outform DER -in e:/certs/crt/sktestca.crt -out e:/certs/crt/sktestca.der'); #1) Create a private key for the server or the website. This may be application-specific, we will create a private key for stunnel and #for apache. The server is called 'freja'. #This creates an unencrypted key with 1024 bits key length. mkdir('e:/certs/server'); system($openssl.' genrsa -out e:/certs/server/freja.key 1024'); mkdir('e:/certs/httpd'); system($openssl.' genrsa -out e:/certs/httpd/freja.key -des3 1024'); #Display contents of key using # system($openssl.' rsa -noout -text -in e:/certs/httpd/freja.key'); #2) Create a certificate signing request (CSR) for the server key(s). #This is the request asking the Certificate Authorithy to sign the association "server public key - server Distinguished Name (DN)" using its private key. #Decide what you want to have certified: #- what public key #- what's the DN information that should appear in the certificate? #Notice that the certification routines will balk at having to recertify a CSR that has exactly the same DN as one already certified. print("Creating csr's for httpd/freja.csr\n"); system($openssl.' req -new -key e:/certs/httpd/freja.key -out e:/certs/httpd/freja.csr -config e:/certs/openssl.cnf'); print("Creating csr's for server/freja.csr\n"); system($openssl.' req -new -key e:/certs/server/freja.key -out e:/certs/server/freja.csr -config e:/certs/openssl.cnf'); if($debug) { #To check the request's contents: system($openssl.' req -noout -text -in e:/certs/httpd/freja.csr'); system($openssl.' req -noout -text -in e:/certs/server/freja.csr'); #...the request is of course NOT encrypted in any way #The command needs the earlier generated server private key so that a signature proving you have the private key of the public key you want to have #signed can be added to the CSR. If you private key was encrypted, you are asked for the password to it. #The request contains the server public key + DN information to be certified and a signature, obtained using the private key associated to the public key. #There is also a 'challenge password' (probably for exchange betweenreq -verify -in e:/certs/httpd/freja.csr CA and certification requestor) #To verify the signature on a request: #system($openssl.' req -verify -in e:/certs/httpd/freja.csr'); #system($openssl.' req -verify -in e:/certs/server/freja.csr'); #This should work as follows: take the signature of the csr, decrypt it using the public key in the csr, then match the hashvalue thus obtained #to the hashvalue of the public key in the csr. If these match, the requestor indeed owns the private key to the public key to be signed. #Make your own copy /usr/share/ssl/openssl.cnf for parametrization. # #At this point, the signing request is sent to the root CA, which would probably call up the requestor to 'know your customer'. } #After that, the root CA will sign the request. Which is what we do now: #3) Sign the certificate signing request yielding a valid certificatereq -verify -in e:/certs/httpd/freja.csr, using the root CA created earlier. chdir('e:/certs/ca'); system($openssl.' ca -in e:/certs/server/freja.csr -cert e:/certs/crt/sktestca.crt -keyfile e:/certs/key/sktestca.key -days 360 -extensions v3_ca -config e:/certs/openssl.cnf'); system($openssl.' ca -in e:/certs/httpd/freja.csr -cert e:/certs/crt/sktestca.crt -keyfile e:/certs/key/sktestca.key -days 360 -config e:/certs/openssl.cnf'); #openssl x509 -text -in e:/certs/crt/sktestca.crt #4) Copy the freja (signed) certificate to its final destination: system('copy e:\certs\ca\demoCA\newcerts\01.pem e:\certs\server\freja-cert.pem'); system('copy e:\certs\ca\demoCA\newcerts\02.pem e:\certs\httpd\freja-cert.pem'); #Make the files available to Apache SSL #1) Apache has to know where it should get the server's private key from: #SSLCertificateKeyFile e:/certs/httpd/freja.key # #2) Apache has to know where it should get the server's signed certificate from: #SSLCertificateFile e:/certs/httpd/freja-cert.pem #1) Create a private key for a client (called hydrogen) This key must NOT be encrypted (at least for stunnel 4.03): system($openssl.' genrsa -out e:/certs/client/hydrogen.key 1024'); #2) Create a Certificate Signing Request: system($openssl.' req -new -key e:/certs/client/hydrogen.key -out e:/certs/client/hydrogen.csr -config e:/certs/openssl.cnf'); #3) Sign the Certificate using the Stunnel Server's (freja) Key: chdir('e:/certs/ca'); system($openssl.' ca -in e:/certs/client/hydrogen.csr -cert e:/certs/server/freja-cert.pem -keyfile e:/certs/server/freja.key -days 350 -extensions v3_ca -config e:/certs/openssl.cnf'); system('copy e:\certs\ca\demoCA\newcerts\03.pem e:\certs\client\hydrogen-cert.pem');