Tag Archives: crypto - Page 2

Generating (Very) Large Primes

Have you ever wondered how big the “large primes” that RSA encryption is based on really are? What exactly does a “1024-bit” key mean anyway? And if the difficulty of RSA is partially based on factoring large numbers, how do we create these large primes without determining primality via factorization?

The easiest way to demonstrate these concepts is with a simple script, so let’s take a look at a large random number generator I wrote1 using Python. As is typical for this blog, you’ll note that the random numbers are not cryptographically secure. To make these examples simple I don’t want to introduce external dependencies, but please keep that issue in mind for any serious applications of the code presented here.

import random
import math
import sys
 
def rabinMiller(n):
     s = n-1
     t = 0
     while s&1 == 0:
         s = s/2
         t +=1
     k = 0
     while k<128:
         a = random.randrange(2,n-1)
         #a^s is computationally infeasible.  we need a more intelligent approach
         #v = (a**s)%n
         #python's core math module can do modular exponentiation
         v = pow(a,s,n) #where values are (num,exp,mod)
         if v != 1:
             i=0
             while v != (n-1):
                 if i == t-1:
                     return False
                 else:
                     i = i+1
                     v = (v**2)%n
         k+=2
     return True
 
def isPrime(n):
     #lowPrimes is all primes (sans 2, which is covered by the bitwise and operator) 
     #under 1000. taking n modulo each lowPrime allows us to remove a huge chunk 
     #of composite numbers from our potential pool without resorting to Rabin-Miller
     lowPrimes =   [3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97
                   ,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179
                   ,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269
                   ,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367
                   ,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461
                   ,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571
                   ,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661
                   ,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773
                   ,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883
                   ,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]
     if (n >= 3):
         if (n&1 != 0):
             for p in lowPrimes:
                 if (n % p == 0):
                     return False
             return rabinMiller(n)
     return False
 
def generateLargePrime(k):
     #k is the desired bit length
     r=100*(math.log(k,2)+1) #number of attempts max
     r_ = r
     while r>0:
        #randrange is mersenne twister and is completely deterministic
        #unusable for serious crypto purposes
         n = random.randrange(2**(k-1),2**(k))
         r-=1
         if isPrime(n) == True:
             return n
     return "Failure after "+`r_` + " tries."
 
print generateLargePrime(1024)

This code is very slow, but does not represent an entirely naïve approach.2  To generate a prime we first create a random integer in the range (2k-1,2k), then the following rules are applied:

  1. The number (n) must be >=3.  While 2 is a prime number, for our purposes we have no interest in numbers less than 3.
  2. Do a bitwise and (n&1).  If the result is not 0 then we know the number is even and can throw it out.
  3. Check that n%p is 0 (in other words, that n is not divisible evenly by p) for all primes <1000.  This check will eliminate a large quantity of composite numbers and prevent the expense of the next test.
  4. Finally we reach the core test: Rabin-Miller.  This algorithm, if it returns true, states that there is a 75% chance that the number is prime (for the randomly chosen basis a).  To obtain a 2-128 chance that the number is not prime, we must repeatedly run the Rabin-Miller test choosing different number bases. Since each iteration of the test increases our probability by a power of 2 we must iterate 64 times to reach this confidence level.

 
If the number passes all these tests it is returned as a valid prime number. Of course, if you don’t trust the output from this script you can always check it with openssl…

openssl prime 7337488745629403488410174275830423641502142554560856136484326749638755396267050319392266204256751706077766067020335998122952792559058552724477442839630133
8C18E5DC98684E2A15B84535635A95C4A192B73B40A780AB4CB0C58BDB9C31EF970C3AC6D804712B830FB6F1B140693A251E989F89B687EBA62781AD031D5135 is prime

 Click for an example of an 8192-bit prime created with the generateLargePrime() function. You can also check out a 1024-bit prime as well. 1024-bit keys are the minimum size recommended for end entity certificates using RSA (SSL certificates) at this time.3

Of course, a large prime is nice, but it isn’t necessarily an RSA prime. Look for another entry soon explaining the additional restrictions imposed by RSA.

  1. This code is based on the pseudocode provided in Practical Cryptography.
  2. Generation of a 1024-bit prime using this script takes 5-10 seconds, whereas OpenSSL takes 0.1-0.2 seconds.
  3. NIST guidelines suggest migration to 2048-bit keys by 31 Dec 2010)

Re-Signing An Expired CA Certificate

On rare occasions you may find yourself with a self-signed internal CA that has expired while you are still using certificates issued from the CA. One potential solution to this problem is to self-sign a new cert with identical fields using the private key from the old certificate.1

You can fill in almost all the fields using the interactive prompt, but to ensure maximum compatibility be sure every field matches exactly. You will also need to set the serial number of the certificate via the -set_serial parameter (openssl takes this argument in decimal form, not hex)2.

openssl req -new -x509 -key previousprivatekey.pem -set_serial 0000 -out newroot.cer

You now have a new root certificate that will work with your previously issued certificates!

  1. In general this is very bad practice, but this article presupposes that you recognize this and it is still necessary.
  2. If you fail to set the serial identically Microsoft OSes will chain the certificate correctly but OpenSSL will fail.

OpenSSL SAN/UCC Certificate Generation

Signing a CSR containing subjectAltName (SAN/UCC) extensions isn’t hard, but can be a daunting challenge for the OpenSSL neophyte. We’re going to use the OpenSSL Self-Signed CA to accomplish this task in two ways.

Pre-Existing SAN CSR

Either you already have a SAN CSR from another source or you generated one using the tutorial from yesterday. Inside your myca.conf file you’ll need to add the following under the [ myca ] section.

copy_extensions	= copy

Now you can simply sign the CSR using the method specified in the self-signed CA post and you’re all set.

Add SAN/UCC Extensions to Existing CSR

To accomplish this add the following to your myca.conf under the [ myca_extensions ] section.

subjectAltName          = @alt_names

Then add this section at the end of the file.

[alt_names]
DNS.1   = test.domain.com
DNS.2   = other.domain.com
DNS.3   = www.domain.net

Set the DNS entries under alt_names to what you want (adding DNS.4 = if you need more, et cetera). Be sure you do not have the copy_extensions directive present in your conf.
Once you have done this you can sign any CSR you choose with the command specified in the self-signed CA article and it will add the specified subjectAltName attributes to the certificate.

Creating a SubjectAltName (SAN/UCC) CSR

SAN certificates (or as Microsoft and others have taken to calling them, Unified Communications Certificates) are rapidly becoming a popular option for securing multiple domains. In fact, Exchange 2007, OCS 2007, and several other products now require UCC to function. However, this certificate type can proffer some advantages beyond that of a wildcard certificate as well. One such advantage is the ability to secure “domain.com”, “www.domain.com”, “domain.net”, and “someotherdomain.com” all within a single certificate.

SAN CSRs cannot be generated using the interactive prompt in OpenSSL so we’ll need to make a conf:

[ req ]
default_bits        = 1024
default_keyfile     = privkey.pem
distinguished_name  = req_distinguished_name
req_extensions     = req_ext # The extentions to add to the self signed cert
 
[ req_distinguished_name ]
countryName           = Country Name (2 letter code)
countryName_default   = US
stateOrProvinceName   = State or Province Name (full name)
stateOrProvinceName_default = Illinois
localityName          = Locality Name (eg, city)
localityName_default  = Chicago
organizationName          = Organization Name (eg, company)
organizationName_default  = Example, Co.
commonName            = Common Name (eg, YOUR name)
commonName_max        = 64
 
[ req_ext ]
subjectAltName          = @alt_names
 
[alt_names]
DNS.1   = test.domain.com
DNS.2   = other.domain.com
DNS.3   = www.domain.net

You will need to set your alt_names section to the FQDNs you wish to use. If you need more simply add “DNS.4 = whatever.com” and so on. Once you have done that, save the file as “req.conf” and then execute openssl!

openssl req -new -nodes -out myreq.csr -config req.conf
Generating a 1024 bit RSA private key
............................................................++++++
..++++++
writing new private key to 'privkey.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:US
State or Province Name (full name) [Illinois]:Illinois
Locality Name (eg, city) [Chicago]:Chicago
Organization Name (eg, company) [Example, Co.]:Example, Co.
Common Name (eg, YOUR name) []:www.domain.com

You now have a “myreq.csr” and a “privkey.pem” associated with the CSR. You can now submit this CSR to a CA for signing or sign it with your own self-signed CA. A tutorial to perform the latter will be published in a few days!

Code Signing for Mac OS X and Windows

Code signing is rapidly becoming an important part of application deployment on many platforms. On OS X it suppresses the keychain warnings when you update your application and on Windows it can bypass numerous UAC notifications as well as the initial application launch dialog. This can (sometimes drastically) improve the customer experience and reduce friction associated with your application. But how do you actually do it?

You can purchase a code signing certificate from any major CA, but for today we’re going to use the OpenSSL Self-Signed CA we created in a previous article.

First let’s create a code signing certificate (if you purchased a certificate you will not need to perform these steps):

 openssl req -newkey rsa:1024 -nodes -out codesign.csr -keyout codesign.key

This will write out a codesign.key and codesign.csr after you choose the fields you desire. Since we are making a code signing certificate the common name should be your company name. You can also leave the challenge password blank.

Generating a 1024 bit RSA private key
..........++++++
..................++++++
writing new private key to 'req.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:US
State or Province Name (full name) [Berkshire]:Illinois
Locality Name (eg, city) [Newbury]:Chicago
Organization Name (eg, company) [My Company Ltd]:End Entity, Inc.
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:End Entity, Inc.
Email Address []:
 
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Now that we’ve created the CSR, we need to modify the myca.conf file to flag certificates for code signing. Find this line

extendedKeyUsage = serverAuth

and change it to

extendedKeyUsage = codeSigning

Now we’re all set to sign the certificate.

 openssl ca -batch -config /path/to/myca.conf -notext -in codesign.csr -out /path/to/codesign.cer

At this point we should have a codesign.cer and a codesign.key file and we’re ready for the actual signing process.

Code Signing on OS X

In OS X the codesign binary is used to sign applications. Codesign cannot accept the private key/certificate pair as a command line parameter, so you must place them in your Keychain. To do this you need to convert your CER + RSA private key into a PKCS12 (PFX) file. Luckily there’s already a post here about that, so check out Generating a PKCS12 (PFX) Via OpenSSL for more information.
Once you have it in the proper format, simply double click to import. Now to sign your application:

codesign -s 'End Entity, Inc.' Whatever.app

Inside the single quotes you’ll want to choose the name (CN) of the certificate as seen in Keychain Access.
If you chose to sign the application with a self-signed cert, please note that OS X won’t trust it unless you add the created root to your Keychain. If you do not you will receive this warning:

Whatever.app/: CSSMERR_TP_NOT_TRUSTED

Code Signing XP/Vista/Windows 7

To code sign in Windows you should have an SPC (aka PKCS7/P7B) or CER file along with a pvk formatted private key. To take a standard RSA private key and convert to PVK you should use PVK Tool (Download link is under the conversion tools heading)
Convert your private key to PVK format

pvk.exe -topvk -nocrypt -in codesign.key -out codesign.pvk

Once you have the files in the format you require execute SignTool from a windows command prompt.

 signtool.exe signwizard


And we’re done! If you chose to sign the application with a self-signed cert, please note that Windows won’t trust it unless you add the created root to your certificate store.

AES Encryption Via OpenSSL

If you have ever wanted to encrypt a blob of data for transmission or archival, OpenSSL provides a simple way to accomplish this task without resorting to platform specific tools.
To encrypt1:

openssl enc -e -aes-256-cbc -in filename -out filename.enc

To decrypt:

openssl enc -d -aes-256-cbc -in filename.enc -out filename.dec

The example above uses AES256 in cipher block chaining mode, however there are almost 50 different cipher functions available for encryption. To see a list, just type openssl enc help. I would very seriously recommend staying with well-known and accepted standard ciphers like AES unless you have an explicit need to choose something more esoteric.

  1. You can also add -a to encode to base64 so you can easily send via email or other methods that don’t support binary encoding.