Having introduced the the notion of an encryption key,
we turn our attention to **symmetric-key encryption**. This is the
case where the **same key** is used to both encrypt and decrypt.
It sometimes called **secret-key encryption**,
**single-key encryption** or simply *symmetric encryption*.

In traditional fashion, we'll assume that Alice wants to send some data securely to Bob. This means Alice is going to encrypt the data, and then when he receives it, Bob will decrypt it again. Firstly, somehow or other, Alice and Bob have to agree between them on what the secret key will be. We'll assume that the key is some sequence of bytes of an appropriate length. (We mentioned in our inntroduction to encryption keys that in fact, with certain algorithms, you have to make sure the key has a certain structure and/or avoid "weak" keys; in fact, it turns out that for our particular example this won't be a problem.) In a moment, we'll come back to the problem of how the key is chosen, what length it should be, and how Alice and Bob can agree in advance on what that key is. For now, let's pretend they "just know" what the secret key is, and worry about the Java code that they each run to actually encrypt and decrypt their data.

In this example, we're going to use a widely-adopted encryption algorithm called AES. (We'll consider one or two other algorithms later. But in general, if you need to use a symmetric encryption system and you're not sure which algorithm to pick, AES is probably the one you'll end up using unless you have a strong reason to use something else.) Then, as a first attempt (which we will need to revise), this is essentially the pattern for encryption/decryption:

Alice's encryption code | Bob's decryption code |

byte[] key = //... secret sequence of bytes byte[] dataToSend = ... Cipher c = Cipher.getInstance("AES"); SecretKeySpec k = new SecretKeySpec(key, "AES"); c.init(Cipher.ENCRYPT_MODE, k); byte[] encryptedData = c.doFinal(dataToSend); // now send encryptedData to Bob... |
byte[] key = //... we know the secret! byte[] encryptedData = //... received from Alice Cipher c = Cipher.getInstance("AES"); SecretKeySpec k = new SecretKeySpec(key, "AES"); c.init(Cipher.DECRYPT_MODE, k); byte[] data = c.doFinal(encryptedData); // do something with data |

If you want to test this code, just pick any 16-byte sequence as the key.
If you put the same key into each side, you should find that data encrypted by
Alice's code can be decrypted by Bob's. And if you try printing out the encrypted
bytes, you should find that it looks like a series of undecipherable random bytes.
Indeed, in principle at least, these bytes will be *computationally* undecipherable
without the key.

But unfortunately, that's not the whole story... To see why, we need to first consider how AES and similar algorithms work, and in particular the notion of block ciphers.

Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.