• Aucun résultat trouvé

PADDING METHODS

Dans le document WITH JAVA APPLETS CRYPTOGRAPHY INTRODUCTION TO (Page 135-141)

Linear Ciphers

5.8 PADDING METHODS

FIGURE 5.3

00000011 00000011 00000011

Message Padding

... ... ...

though they are used in many applications today. Thus, we continue to develop better enci-phering methods. However, before we move on to the next topic, we need to address the topic of padding.

5.8 PADDING METHODS

Note that when we use block ciphers, the size of the message we are sending may not be a multiple of the block size. For example, when we are using a block size of four,

HOWDY DOO = HOWD YDOO is a perfect multiple of the block size, but

HOWDY FOLKS = HOWD YFOL KS

is not. When this happens, we must pad the end of the message so that it becomes a perfect block. We may choose to pad with some character, such as the letter X, as in

HOWD YFOL KSXX

or we may pad with zeros once we have converted the message into its numerical equiva-lent, like

07142203 24051411 10180000.

This is not really satisfactory, as the characters or digits that we choose to pad with may well be a valid part of the message, and not padding at all. This might possibly create con-fusion at the receiving end. One solution to this problem is PKCS#5, a proposed standard method of padding.

PKCS#5 Padding. This type of padding works like this: suppose the block size is 64 bytes, and the message is 125 bytes long. This makes 1 complete block, plus 61 bytes, 3 bytes short of a full block. To complete the block, we append 3 bytes, each containing the num-ber 3, as seen in Figure 5.3 (in binary):

The message is now encrypted, and sent. On the receiving end, the message is decrypted.

The last block is inspected, and the last 3 bytes, each containing the number 3, are removed.

In general, if our message is Nbytes short of a full block, we append Nblocks, each con-taining the number N.

What if our last block is complete? With PKCS#5, we add padding anyway! If our block size is 64 bytes, and our message is 128 bytes, we will still append 64 bytes (each byte con-taining the number 64) to the message! Why is this done? Suppose the message being sent is an exact multiple of the block size. Now, suppose the last 6 bytes of the message happen to contain the number 6. How is the receiver to know whether this is padding or part of the

FIGURE 5.4

11111111 11111111 11111111

(message) ...

255 bytes of padding

message? She doesn’t. This is why we append an entire block to messages that are already perfect multiples of the block size.

Note that PKCS#5 padding has a limitation: It cannot be used for ciphers in which the ciphertext block size exceeds 255 bytes. This should be simple to see if you note that each byte of padding in PKCS#5 contains a binary number revealing the number of bytes of padding. Clearly, 11111111(base 2)= 255 is the largest number we can write in a byte, so a com-plete block of 255 bytes would be padded as shown in Figure 5.4.

Java Algorithm. Block ciphers are difficult to write, not because the enciphering trans-formations are any more difficult, but because you must pad/unpad and block/unblock the messages. To do all this, we will write a Ciphers class; it will contain methods to do all the blocking and padding activities, and methods to encipher and decipher using various trans-formations. The first will be the block affine transformation. For better readability (hope-fully), the explanation for the code is interspersed with the code:

import java.math.*;

public class Ciphers {

The following is the padding method. You pass in the message and the block size. It computes the number of blocks, then pads using the PKCS#5 scheme. This means padding is added even if the message is a perfect multiple of the block size. It also means that any ciphers using this method are effectively limited to a maximum block size of 255 bytes.

private static byte[] pad(byte[] msg,int blockSize) { //Check that block size is proper for PKCS#5 padding if (blockSize<1||blockSize>255) throw new

IllegalArgumentException(“Block size must be between 1 and 255.”);

//Pad the message

int numberToPad=blockSize-msg.length%blockSize;

byte[] paddedMsg=new byte[msg.length+numberToPad];

System.arraycopy(msg,0,paddedMsg,0,msg.length);

for (int i=msg.length;i<paddedMsg.length;i++) paddedMsg[i]=(byte)numberToPad;

return paddedMsg;

}

This method takes a padded message, then converts it to a 2-dimensional byte array.

Each “vector” in this 2D array is a block. The enciphering methods will work with this 2D array.

5.8 Padding Methods 121

private static byte[][] block(byte[] msg,int blockSize) {

//Create a 2D array of bytes corresponding to the message-all blocks should be //full

int numberOfBlocks=msg.length/blockSize;

byte[][] ba=new byte[numberOfBlocks][blockSize];

for (int i=0;i<numberOfBlocks;i++) for (int j=0;j<blockSize;j++)

ba[i][j]=msg[i*blockSize+j];

return ba;

}

This method “unblocks” the message; that is, after the enciphering or deciphering trans-formation, it takes the 2D array of blocks, then converts it back to a linear array of bytes.

The method must be careful to take into account that the enciphering or deciphering trans-formation may produce an integer smaller than the block size. In that case, it fills in the lin-ear array from the rlin-ear of the block.

private static byte[] unBlock(byte[][] ba,int blockSize) { //Create the 1D array in which to place the enciphered blocks byte[] m2=new byte[ba.length*blockSize];

//Place the blocks in the 1D array for (int i=0;i<ba.length;i++) {

int j=blockSize-1;

int k=ba[i].length-1;

while (k>=0) {

m2[i*blockSize+j]=ba[i][k];

k--;

j--;

} }

return m2;

}

This method removes the padding. All it has to do is examine the numerical value in the last block, then remove exactly that many blocks.

private static byte[] unPad(byte[] msg,int blockSize) { //Determine the amount of padding-just look at last block int numberOfPads=(msg[msg.length-1]+256)%256;

//Chop off the padding and return the array byte[] answer=new byte[msg.length-numberOfPads];

System.arraycopy(msg,0,answer,0,answer.length);

return answer;

}

Finally, here are the enciphering and deciphering methods for the block affine cipher. Each accepts a message, the block size, and the values of aandbfrom the enciphering transfor-mation

C⬅aP+b.

public static byte[] affineEncipher(byte[] msg,int blockSize,BigInteger a,BigInteger b) {

//Compute the modulus

BigInteger modulus=BigInteger.valueOf(2).pow(8*blockSize);

//Check the multiplier

if (!(modulus.gcd(a).equals(BigIntegerMath.ONE))) throw new

IllegalArgumentException(“Enciphering key is not relatively prime to the modulus.”);

byte ba[][]=block(pad(msg,blockSize),blockSize);

//Begin the enciphering for (int i=0;i<ba.length;i++)

ba[i]=getBytes(a.multiply(new BigInteger(ba[i])).add(b).mod(modulus));

return unBlock(ba,blockSize);

}

public static byte[] affineDecipher(byte[] msg,int blockSize,BigInteger a,BigInteger b) {

//Compute the modulus

BigInteger modulus=BigInteger.valueOf(2).pow(8*blockSize);

//Check the multiplier

if (!(modulus.gcd(a).equals(BigIntegerMath.ONE))) throw new

IllegalArgumentException(“Enciphering key is not relatively prime to the modulus.”);

//Compute inverse of a

BigInteger ainv=a.modInverse(modulus);

byte[][] ba=block(msg,blockSize);

//Begin the deciphering for (int i=0;i<ba.length;i++)

ba[i]=getBytes(BigIntegerMath.lnr(ainv.multiply(new BigInteger(ba[i]).subtract(b)),modulus));

//Go from blocks to a 1D array, and remove padding; return this return unPad(unBlock(ba,blockSize),blockSize);

}

This following method is necessary. In order to encipher or decipher, at some point we convert BigIntegers back into an array of bytes using the toByteArray() method from the BigInteger class. This method, in addition to returning the binary representation of the Big-Integer, also returns a sign bit in the high order bit position. This can screw up everything if the BigInteger already fills up the block; in this case the extra sign bit forces another byte to be created. When this happens, we must remove the forward byte. This is never a prob-lem for us, as all of the BigIntegers we use are positive; thus the sign bit is always 0.

5.8 Padding Methods 123

FIGURE 5.5

//Method to rectify the extra bit problem of the toByteArray() method private static byte[] getBytes(BigInteger big) {

byte[] bigBytes=big.toByteArray();

if (big.bitLength()%8!=0) return bigBytes;

else {

byte[] smallerBytes=new byte[big.bitLength()/8];

System.arraycopy(bigBytes,1,smallerBytes,0,smallerBytes.length);

return smallerBytes;

} }

This is the end of the Ciphers class. More methods will be added later, as we develop more cryptosystems.

}

I have written an applet called TestBlockAffineCipherApplet to test this cipher. The applet can be viewed online at the book’s website. Two screen shots are shown in Figures 5.5 and 5.6.

FIGURE 5.6

EXERCISES

1. Writing a program to encipher and decipher individual characters using affine trans-formations is very easy. All you need do is use a method that computes inverses mod n, and the rest is as easy as writing the Caesar cipher. Write a TestAffineCipherApplet class which tests the two static methods affineEncipher(), and affineDecipher(). These last two methods should accept an array of bytes (a message), along with the enci-phering key(s), and return an array of bytes. You must use primitive ints, so you need to write a method to compute inverses modulo nfor ints.

2. Encipher, and then decipher, the following messages using Caesar shift transforma-tions with the ordinary alphabet, and where the shift b= 23.

a. KENNEDY IS DEAD b. HITLER IN PERU c. BIG BROTHER

3. Repeat the previous exercise but use a single character affine cipher with a multiplier of 15 and a shift of 6.

4. Repeat the previous exercise, but use a block affine cipher with a block size of 4 char-acters per block. Use 25252526, the appropriate value for the modulus (using the ordi-nary alphabet), and use 1542327 for the multiplier, and 9923411 for the shift. Pad messages that are not multiples of the block size with the letter X.

C H A P T E R 6

Dans le document WITH JAVA APPLETS CRYPTOGRAPHY INTRODUCTION TO (Page 135-141)