__CRYPTOGRAPHY__

Cryptography is the science of using mathematics to encrypt and decrypt data. Cryptography enables you to store sensitive information or transmit it across insecure networks (like the Internet) so that it cannot be read by anyone except the intended recipient.

Cryptology embraces both cryptography and cryptanalysis.

__Strong cryptography__

There are two kinds of cryptography in this world: cryptography that will stop your kid sister from reading your files, and cryptography that will stop major governments from reading your files. This book is about the latter.

--Bruce Schneier, Applied Cryptography: Protocols, Algorithms, and Source Code in C.

OpenPGP is also about the latter sort of cryptography. Cryptography can be strong or weak, as explained above. Cryptographic strength is measured in the time and resources it would require to recover the plaintext. The result of strong cryptography is ciphertext that is very difficult to decipher without possession of the appropriate decoding tool. How difficult? Given all of today's computing power and available time — even a billion computers doing a billion checks a second — it is not possible to decipher the result of strong cryptography before the end of the universe.

__How does cryptography work?__

A cryptographic algorithm, or cipher, is a mathematical function used in the encryption and decryption process. A cryptographic algorithm works in combination with a key — a word, number, or phrase — to encrypt the plaintext. The same plaintext encrypts to different ciphertext with different keys. The security of encrypted data is entirely dependent on two things: the strength of the cryptographic algorithm and the secrecy of the key.

A cryptographic algorithm, plus all possible keys and all the protocols that make it work comprise a cryptosystem. OpenPGP is a cryptosystem.

**Caesar's Cipher**

An extremely simple example of conventional cryptography is a substitution cipher. A substitution cipher substitutes one piece of information for another. This is most frequently done by offsetting letters of the alphabet. Two examples are Captain Midnight's Secret Decoder Ring, which you may have owned when you were a kid, and Julius Caesar's cipher. In both cases, the algorithm is to offset the alphabet and the key is the number of characters to offset it.

For example, if we encode the word "SECRET" using Caesar's key value of 3, we offset the alphabet so that the 3rd letter down (D) begins the alphabet.

So starting with

ABCDEFGHIJKLMNOPQRSTUVWXYZ

and sliding everything up by 3, you get

DEFGHIJKLMNOPQRSTUVWXYZABC

where D=A, E=B, F=C, and so on.

Using this scheme, the plaintext, "SECRET" encrypts as "VHFUHW." To allow someone else to read the ciphertext, you tell them that the key is 3.

Obviously, this is exceedingly weak cryptography by today's standards, but hey, it worked for Caesar, and it illustrates how conventional cryptography works.

__Generating an Encryption Key__

The following code generates a java.security.Key that is a valid DES algorithm encryption key.

private Key key;

private void generateKey() throws NoSuchAlgorithmException {

KeyGenerator generator;

generator = KeyGenerator.getInstance("DES");

generator.init(new SecureRandom());

key = generator.generateKey();

}

the method getInstance(String algorithm) of the javax.crypto.KeyGenerator class, returns javax.crypto.KeyGenerator objects for the algorithm.

The generator object must then be initialized with a java.security.SecureRandom that grants secure random numbers, as we need the random number to be cryptographically strong.

Finally we can generate the secret encryption key, this is done using the method generateKey() that returns the java.security.Key that we need.

Encrypt the message

Now we get into the interesting part of the game, the encryption of a message.

There are three steps involved in this:

building the Cipher object that will be responsible of doing the encryption.

converting the message to a format suitable for the Cipher

converting the encrypted message to a format that will be easy

to read on screen (this step is not really needed, but we do it

)

See the comments in the code for details:

private String encrypt(String message) throws IllegalBlockSizeException,

BadPaddingException, NoSuchAlgorithmException,

NoSuchPaddingException, InvalidKeyException,

UnsupportedEncodingException {

// Get a cipher

object.

Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

cipher.init(Cipher.ENCRYPT_MODE, key);

// Gets the raw bytes to encrypt, UTF8 is needed for

// having a

standard character set

byte[]

stringBytes = message.getBytes("UTF8");

// encrypt using the cypher

byte[] raw =

cipher.doFinal(stringBytes);

// converts to

base64 for easier display.

BASE64Encoder encoder = new BASE64Encoder();

String base64 =

encoder.encode(raw);

return base64;

}

__Decrypting a message__

The steps for decrypting the message are basically doing the reverse steps in the reverse order as the encryption:

Obtain a Cipher, same as for the encryption, just now it's in DECRYPT_MODE

decode the BASE64 coded message, we need to pass in to the decrypter exactly the same string that we got out from the encrypter.

Decrypt the message using the Cipher

Convert the decrypted byte array to the String so it can be printed easily

Note: the only data in common between the encryption and the decryption methods is the key.

private String decrypt(String encrypted) throws InvalidKeyException,

NoSuchAlgorithmException, NoSuchPaddingException,

IllegalBlockSizeException, BadPaddingException, IOException {

// Get a cipher

object.

Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

cipher.init(

Cipher.DECRYPT_MODE, key);

//decode the

BASE64 coded message

BASE64Decoder decoder = new BASE64Decoder();

byte[] raw =

decoder.decodeBuffer(encrypted);

//decode the message

byte[] stringBytes =

cipher.doFinal(raw);

//

converts the decoded message to a String

String clear = new String(stringBytes, "UTF8");

return clear;

}

This should be the end result: