1 package org.bouncycastle.crypto.encodings;
3 import java.security.SecureRandom;
5 import org.bouncycastle.crypto.CipherParameters;
6 import org.bouncycastle.crypto.AsymmetricBlockCipher;
7 import org.bouncycastle.crypto.InvalidCipherTextException;
8 import org.bouncycastle.crypto.params.ParametersWithRandom;
9 import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
12 * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
13 * depends on your application - see PKCS1 Version 2 for details.
15 public class PKCS1Encoding
16 implements AsymmetricBlockCipher
18 private static int HEADER_LENGTH = 10;
20 private SecureRandom random;
21 private AsymmetricBlockCipher engine;
22 private boolean forEncryption;
23 private boolean forPrivateKey;
26 AsymmetricBlockCipher cipher)
31 public AsymmetricBlockCipher getUnderlyingCipher()
37 boolean forEncryption,
38 CipherParameters param)
40 AsymmetricKeyParameter kParam;
42 if (param instanceof ParametersWithRandom)
44 ParametersWithRandom rParam = (ParametersWithRandom)param;
46 this.random = rParam.getRandom();
47 kParam = (AsymmetricKeyParameter)rParam.getParameters();
51 this.random = new SecureRandom();
52 kParam = (AsymmetricKeyParameter)param;
55 engine.init(forEncryption, kParam);
57 this.forPrivateKey = kParam.isPrivate();
58 this.forEncryption = forEncryption;
61 public int getInputBlockSize()
63 int baseBlockSize = engine.getInputBlockSize();
67 return baseBlockSize - HEADER_LENGTH;
75 public int getOutputBlockSize()
77 int baseBlockSize = engine.getOutputBlockSize();
85 return baseBlockSize - HEADER_LENGTH;
89 public byte[] processBlock(
93 throws InvalidCipherTextException
97 return encodeBlock(in, inOff, inLen);
101 return decodeBlock(in, inOff, inLen);
105 private byte[] encodeBlock(
109 throws InvalidCipherTextException
111 byte[] block = new byte[engine.getInputBlockSize()];
115 block[0] = 0x01; // type code 1
117 for (int i = 1; i != block.length - inLen - 1; i++)
119 block[i] = (byte)0xFF;
124 random.nextBytes(block); // random fill
126 block[0] = 0x02; // type code 2
129 // a zero byte marks the end of the padding, so all
130 // the pad bytes must be non-zero.
132 for (int i = 1; i != block.length - inLen - 1; i++)
134 while (block[i] == 0)
136 block[i] = (byte)random.nextInt();
141 block[block.length - inLen - 1] = 0x00; // mark the end of the padding
142 System.arraycopy(in, inOff, block, block.length - inLen, inLen);
144 return engine.processBlock(block, 0, block.length);
148 * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
150 private byte[] decodeBlock(
154 throws InvalidCipherTextException
156 byte[] block = engine.processBlock(in, inOff, inLen);
158 if (block.length < getOutputBlockSize())
160 throw new InvalidCipherTextException("block truncated");
163 if (block[0] != 1 && block[0] != 2)
165 throw new InvalidCipherTextException("unknown block type");
169 // find and extract the message block.
173 for (start = 1; start != block.length; start++)
175 if (block[start] == 0)
181 start++; // data should start at the next byte
183 if (start >= block.length || start < HEADER_LENGTH)
185 throw new InvalidCipherTextException("no data in block");
188 byte[] result = new byte[block.length - start];
190 System.arraycopy(block, start, result, 0, result.length);