OpenSSL is the ubiquitous toolkit for writing security applications. It was originally written as an SSL library with specific focus on performance for x86 platrorms but today it has become the de facto standard for implementing user space security applications. What makes OpenSSL so versatile? One look at the featureset will possibly give us the answer. OpenSSL does the following and many more. 1) Supports nearly every symmetric encryption algorithm and message digest algorithm under the sun 2) Supports all the public key encryption technologies including elliptic curve cryptography 3) Has a comprehensive ASN1,Base64 and DER library builtin 4) Given an appropriate random seed, it can generate pseudorandom bits 5) It has support for SSL v2, SSL v3 and TLS v1 6) It implements the X.509 certificate standard with v3 extensions 7) Support for SMIME, PKCS7, PKSC8 and PKCS12 standards and OCSP 8) Supports hardware acceleration 9) Has a low level math library for prime number generation, modulo arithmetic, arbitrary precision multiplications,exponentiations and so on 10) Has a BIO (Basic I/O) abstraction using which you can "chain" filter BIOs with a source/sink BIO I stopped at 10 since the list would be too long if I were to go on. It also has a command line tool which has an interface to almost everything I mentioned above. There are also man pages that describe each command in detail. The library is free for commercial use and there is no obligation to release the source code for the changes. Not surprisingly OpenSSL is popular in the commercial world as well. What is lacking however even after several years of existence in which the library has steadily progressed in terms of features, various enhancements and bug fixes, support for different hardware chips and so on and so forth is a clear lack of proper documentation. Sure, you can walk to the nearby bookstore and pick up the Oreilly book titled "Network Security with OpenSSL". You can also google and come up with a few search results. But none of them give you a true picture of how to use OpenSSL's length and breadth of features. What this article aims to do is not give you advice on security and security practices. We also won't talk about topics covered elsewhere like doing SSL programming with OpenSSL. Instead we will focus on how to give you enough hold of the OpenSSL source code so that you can use OpenSSL profitably. You may have an academic interest or wish to learn the practical aspects of cryptography. Or you may want to hack just for the fun of it. The first thought that comes to most people when they hear security orcryptography is encryption. So why not start with that? Encryption can be very simply explained as a process in which the input issubject to "substitution" and "transposition" otherwise known as confusion anddiffusion to produce an output which is indistinguishable from the input. Infact the diffusion or transposition is so thorough that the output looksalmost random. Which is why there is no point in attempting to compress an encrypted message since compression relies on patterns in input data. So compression should always be done prior to encryption. It is for the substitution stage that we need a secret key. The secretkey is used to transform the input in such a manner that it is very hard toguess the key or the input from the output. And all this is done in such amanner that is perfectly reversible. For decryption , use the same secret key and run the reverse substitutionprocess and the transposition such as to obtain the original back. Obviously this is very simplistic. What happens in reality is that the secret key is used to generate a key sequence which is applied to the input data in multiple rounds with a good amount of shuffling(transposition) thrown in at each round. The input is split into multiple blocks and each block is subject to the above process. The blocks are combined in different ways to make sure that the shuffling is really thorough. In the most secure method of combining blocks called ciper block chaining, each successive block depends on all of its previous blocks. By the way, what I mentioned above is symmetric encryption scheme which iswhat most people mean by encryption. And I spoke about block cipers which isthe most popular. OpenSSL 0.9.8a supports the following symmetric encryption algorithms. 1) AES (Rijndael) 2) Blowfish 3) CAST 4) DES 5) IDEA 6) RC2 7) RC4 8) DES3 Now that we learnt the theory it must be really tempting to see how it worksin practice. That is where having an open source implementation helps in whichwe can really go down to as much depth as we need. For this article however wewill be satisfied with the code to achieve basic encryption and decryption. This is the code for encryption. #include #include #include #define IV "0xdeadbeefdeadbeef" int main(int argc, char **argv) { EVP_CIPHER_CTX ctx; unsigned char key[1024],iv[1024],ibuf[1024],obuf[1024]; int rfd, wfd,keyfd,ilen,olen,tlen;
int l = 0;
if(argc < 3) { printf("Usage: %s infile outfilen",argv[0]); exit(128); }
memcpy(iv,IV,sizeof(IV)); key[0] = 0;
/* Let us derive a random 256 bit key */ while(l < 32) { char b[128]; sprintf(b,"%lu",arc4random()); strcat(key,b); l = strlen(key); }
keyfd = creat(".key",0644); write(keyfd,key,256); close(keyfd);
EVP_CIPHER_CTX_init(&ctx); if(!EVP_CipherInit_ex(&ctx, EVP_aes_256_cbc(),NULL,key, iv,1) ) { printf("Couldnt initialize ciphern"); return 1; } /* 1 for encrypt, 0 for decrypt */
if((rfd = open(argv[1],O_RDONLY) ) == -1) { printf("Couldnt open input filen"); exit(128); } if((wfd = creat(argv[2],0644) ) == -1) { printf("Couldn't open output file for writingn"); exit(128); }
while((ilen = read(rfd,ibuf,1024) ) > 0) { if(EVP_CipherUpdate(&ctx,obuf,&olen,ibuf,ilen)){ write(wfd,obuf,olen); } else { printf("Encryption errorn"); return 1; } } if(!EVP_CipherFinal_ex(&ctx,obuf+olen,&tlen)) { printf("Trouble with padding the last blockn"); return 1; } write(wfd,obuf+olen,tlen); EVP_CIPHER_CTX_cleanup(&ctx); close(rfd); close(wfd);
printf("AES 256 CBC encryption completen"); printf("Secret key is saved to file .keyn");
return 0; } And here is the code for decryption. #include #include #include
#define IV "0xdeadbeefdeadbeef"
int main(int argc, char **argv) { EVP_CIPHER_CTX ctx; unsigned char key[1024],iv[1024],ibuf[1024],obuf[1024]; int rfd, wfd,keyfd,ilen,olen,tlen; int l = 0;
if(argc < 3) { printf("Usage: %s infile outfilen",argv[0]); exit(128); }
memcpy(iv,IV,sizeof(IV)); key[0] = 0;
keyfd = open(".key",O_RDONLY); read(keyfd,key,256); close(keyfd);
EVP_CIPHER_CTX_init(&ctx); /* last parameter 1 for encrypt, 0 for decrypt */ if(!EVP_CipherInit_ex(&ctx, EVP_aes_256_cbc(),NULL,key, iv,0) ) { printf("Couldnt initialize ciphern"); return 1; }
if((rfd = open(argv[1],O_RDONLY) ) == -1) { printf("Couldnt open input filen"); exit(128); }
if((wfd = creat(argv[2],0644) ) == -1) { printf("Couldn't open output file for writingn"); exit(128); }
while((ilen = read(rfd,ibuf,1024) ) > 0) { if(EVP_CipherUpdate(&ctx,obuf,&olen,ibuf,ilen)){ write(wfd,obuf,olen); } else { printf("Decryption errorn"); return 1; } }
if(!EVP_CipherFinal_ex(&ctx,obuf+olen,&tlen)) { printf("Trouble with unpadding the last blockn"); return 1; } write(wfd,obuf+olen,tlen); EVP_CIPHER_CTX_cleanup(&ctx); close(rfd); close(wfd);
printf("AES 256 CBC decryption completen"); return 0; }
As it must be obvious by now the above works best only when sufficientrandomness is present in the key. It helps if the input does not have patternsbut that is not something we can change. There is another encryption methodology called public key encryption orasymmetric cryptography. This is very different from symmetric encryption. I am going to talk about the most popular scheme - the RSA algorithm. The goal of public key cryptography is that of achieving secrecy withoutsharing a secret key first like in the case of symmetric cryptography above.So what happens here is slightly more difficult to follow. There are threecomponents for encryption. One is the modulus whose length is what we mean by 1024 bit RSA, i.e., the modulus is an integer of length 1024 bits. Using the modulus we derive two keys - the public key and the private key. Now there is a relationship between these three entities. Data encrypted with the private key is decryptable only with the public key and vice versa. The modulus is a common entity required for encryption and decryption. The way encryption is done is also very curious. It is modular exponentiation.Needless to say it is hightly computation intensive since very large integersare involved as well as unwieldy forabritrary data. So typically only secret keys are encrypted using RSA. Ormessage digests are encrypted for signing with RSA. The difficulty in cracking an RSA key lies in the difficulty of the factorization of large numbers into two primes. It is very easy to multiply two primes but without one of them , it is nearly impossible to figure out the other multiplicand. So RSA is not something you would want to use for encrypting your file on disk! So RSA is not something you would want to use for encrypting your file on disk!Bear in mind that in OpenSSL public keys are uniquely related to private keys in such a way that you can derive the public key from the private key at any time. Next we come to the topic of message digests. Also known as cryptographichashes or one way functions this class of functions actually have nothing todo with secrecy since they dont directly make your communications secure. Whenused in conjunction with encryption they have an invaluable contribution tomake. So RSA is not something you would want to use for encrypting your file on disk!The goal of message digests is to fingerprint the input data such that even avery minor change(introduction of a space character) or even change in one bitof input data produces an output that is completely different. Another veryimportant property is that no matter what the size of input is, whether it isone byte or a Gigabyte, the output is always of a constant size. As you cansee , message digests are irreversible. It is impossible to construct theinput from the output, that way it is quite different from the two encryptiontechniques we discussed above. We shall see the rest in part II. |