1 package org.bouncycastle.crypto.encodings;
3 import java.math.BigInteger;
4 import java.util.Random;
5 import java.security.SecureRandom;
7 import org.bouncycastle.crypto.CipherParameters;
8 import org.bouncycastle.crypto.AsymmetricBlockCipher;
9 import org.bouncycastle.crypto.InvalidCipherTextException;
10 import org.bouncycastle.crypto.params.ParametersWithRandom;
11 import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
14 * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
15 * depends on your application - see PKCS1 Version 2 for details.
17 public class PKCS1Encoding
18 implements AsymmetricBlockCipher
20 private static int HEADER_LENGTH = 10;
23 //private SecureRandom random;
24 private Random random = new Random();
26 private AsymmetricBlockCipher engine;
27 private boolean forEncryption;
28 private boolean forPrivateKey;
31 AsymmetricBlockCipher cipher)
36 public AsymmetricBlockCipher getUnderlyingCipher()
42 boolean forEncryption,
43 CipherParameters param)
45 AsymmetricKeyParameter kParam;
46 if (param instanceof ParametersWithRandom)
48 ParametersWithRandom rParam = (ParametersWithRandom)param;
51 //this.random = rParam.getRandom();
52 kParam = (AsymmetricKeyParameter)rParam.getParameters();
57 //this.random = new SecureRandom();
58 kParam = (AsymmetricKeyParameter)param;
61 engine.init(forEncryption, kParam);
63 this.forPrivateKey = kParam.isPrivate();
64 this.forEncryption = forEncryption;
67 public int getInputBlockSize()
69 int baseBlockSize = engine.getInputBlockSize();
73 return baseBlockSize - HEADER_LENGTH;
81 public int getOutputBlockSize()
83 int baseBlockSize = engine.getOutputBlockSize();
91 return baseBlockSize - HEADER_LENGTH;
95 public byte[] processBlock(
99 throws InvalidCipherTextException
103 return encodeBlock(in, inOff, inLen);
107 return decodeBlock(in, inOff, inLen);
111 private byte[] encodeBlock(
115 throws InvalidCipherTextException
117 byte[] block = new byte[engine.getInputBlockSize()];
121 block[0] = 0x01; // type code 1
123 for (int i = 1; i != block.length - inLen - 1; i++)
125 block[i] = (byte)0xFF;
130 random.nextBytes(block); // random fill
132 block[0] = 0x02; // type code 2
135 // a zero byte marks the end of the padding, so all
136 // the pad bytes must be non-zero.
138 for (int i = 1; i != block.length - inLen - 1; i++)
140 while (block[i] == 0)
142 block[i] = (byte)random.nextInt();
147 block[block.length - inLen - 1] = 0x00; // mark the end of the padding
148 System.arraycopy(in, inOff, block, block.length - inLen, inLen);
150 return engine.processBlock(block, 0, block.length);
154 * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
156 private byte[] decodeBlock(
160 throws InvalidCipherTextException
162 byte[] block = engine.processBlock(in, inOff, inLen);
163 if (block.length < getOutputBlockSize())
165 throw new InvalidCipherTextException("block truncated");
168 if (block[0] != 1 && block[0] != 2)
170 throw new InvalidCipherTextException("unknown block type");
174 // find and extract the message block.
178 for (start = 1; start != block.length; start++)
180 if (block[start] == 0)
186 start++; // data should start at the next byte
188 if (start >= block.length || start < HEADER_LENGTH)
190 throw new InvalidCipherTextException("no data in block");
193 byte[] result = new byte[block.length - start];
195 System.arraycopy(block, start, result, 0, result.length);