OAEPEncodingpublic class OAEPEncoding extends Object implements org.bouncycastle.crypto.AsymmetricBlockCipherOptimal Asymmetric Encryption Padding (OAEP) - see PKCS 1 V 2. |
Fields Summary |
---|
private byte[] | defHash | private org.bouncycastle.crypto.Digest | hash | private org.bouncycastle.crypto.AsymmetricBlockCipher | engine | private SecureRandom | random | private boolean | forEncryption |
Constructors Summary |
---|
public OAEPEncoding(org.bouncycastle.crypto.AsymmetricBlockCipher cipher)
this(cipher, new SHA1Digest(), null);
| public OAEPEncoding(org.bouncycastle.crypto.AsymmetricBlockCipher cipher, org.bouncycastle.crypto.Digest hash)
this(cipher, hash, null);
| public OAEPEncoding(org.bouncycastle.crypto.AsymmetricBlockCipher cipher, org.bouncycastle.crypto.Digest hash, byte[] encodingParams)
this.engine = cipher;
this.hash = hash;
this.defHash = new byte[hash.getDigestSize()];
if (encodingParams != null)
{
hash.update(encodingParams, 0, encodingParams.length);
}
hash.doFinal(defHash, 0);
|
Methods Summary |
---|
private void | ItoOSP(int i, byte[] sp)int to octet string.
sp[0] = (byte)(i >>> 24);
sp[1] = (byte)(i >>> 16);
sp[2] = (byte)(i >>> 8);
sp[3] = (byte)(i >>> 0);
| public byte[] | decodeBlock(byte[] in, int inOff, int inLen)
byte[] data = engine.processBlock(in, inOff, inLen);
byte[] block = null;
//
// as we may have zeros in our leading bytes for the block we produced
// on encryption, we need to make sure our decrypted block comes back
// the same size.
//
if (data.length < engine.getOutputBlockSize())
{
block = new byte[engine.getOutputBlockSize()];
System.arraycopy(data, 0, block, block.length - data.length, data.length);
}
else
{
block = data;
}
if (block.length < (2 * defHash.length) + 1)
{
throw new InvalidCipherTextException("data too short");
}
//
// unmask the seed.
//
byte[] mask = maskGeneratorFunction1(
block, defHash.length, block.length - defHash.length, defHash.length);
for (int i = 0; i != defHash.length; i++)
{
block[i] ^= mask[i];
}
//
// unmask the message block.
//
mask = maskGeneratorFunction1(block, 0, defHash.length, block.length - defHash.length);
for (int i = defHash.length; i != block.length; i++)
{
block[i] ^= mask[i - defHash.length];
}
//
// check the hash of the encoding params.
//
for (int i = 0; i != defHash.length; i++)
{
if (defHash[i] != block[defHash.length + i])
{
throw new InvalidCipherTextException("data hash wrong");
}
}
//
// find the data block
//
int start;
for (start = 2 * defHash.length; start != block.length; start++)
{
if (block[start] == 1 || block[start] != 0)
{
break;
}
}
if (start >= (block.length - 1) || block[start] != 1)
{
throw new InvalidCipherTextException("data start wrong " + start);
}
start++;
//
// extract the data block
//
byte[] output = new byte[block.length - start];
System.arraycopy(block, start, output, 0, output.length);
return output;
| public byte[] | encodeBlock(byte[] in, int inOff, int inLen)
byte[] block = new byte[getInputBlockSize() + 1 + 2 * defHash.length];
//
// copy in the message
//
System.arraycopy(in, inOff, block, block.length - inLen, inLen);
//
// add sentinel
//
block[block.length - inLen - 1] = 0x01;
//
// as the block is already zeroed - there's no need to add PS (the >= 0 pad of 0)
//
//
// add the hash of the encoding params.
//
System.arraycopy(defHash, 0, block, defHash.length, defHash.length);
//
// generate the seed.
//
byte[] seed = new byte[defHash.length];
random.nextBytes(seed);
//
// mask the message block.
//
byte[] mask = maskGeneratorFunction1(seed, 0, seed.length, block.length - defHash.length);
for (int i = defHash.length; i != block.length; i++)
{
block[i] ^= mask[i - defHash.length];
}
//
// add in the seed
//
System.arraycopy(seed, 0, block, 0, defHash.length);
//
// mask the seed.
//
mask = maskGeneratorFunction1(
block, defHash.length, block.length - defHash.length, defHash.length);
for (int i = 0; i != defHash.length; i++)
{
block[i] ^= mask[i];
}
return engine.processBlock(block, 0, block.length);
| public int | getInputBlockSize()
int baseBlockSize = engine.getInputBlockSize();
if (forEncryption)
{
return baseBlockSize - 1 - 2 * defHash.length;
}
else
{
return baseBlockSize;
}
| public int | getOutputBlockSize()
int baseBlockSize = engine.getOutputBlockSize();
if (forEncryption)
{
return baseBlockSize;
}
else
{
return baseBlockSize - 1 - 2 * defHash.length;
}
| public org.bouncycastle.crypto.AsymmetricBlockCipher | getUnderlyingCipher()
return engine;
| public void | init(boolean forEncryption, org.bouncycastle.crypto.CipherParameters param)
AsymmetricKeyParameter kParam;
if (param instanceof ParametersWithRandom)
{
ParametersWithRandom rParam = (ParametersWithRandom)param;
this.random = rParam.getRandom();
kParam = (AsymmetricKeyParameter)rParam.getParameters();
}
else
{
this.random = new SecureRandom();
kParam = (AsymmetricKeyParameter)param;
}
engine.init(forEncryption, kParam);
this.forEncryption = forEncryption;
| private byte[] | maskGeneratorFunction1(byte[] Z, int zOff, int zLen, int length)mask generator function, as described in PKCS1v2.
byte[] mask = new byte[length];
byte[] hashBuf = new byte[defHash.length];
byte[] C = new byte[4];
int counter = 0;
hash.reset();
do
{
ItoOSP(counter, C);
hash.update(Z, zOff, zLen);
hash.update(C, 0, C.length);
hash.doFinal(hashBuf, 0);
System.arraycopy(hashBuf, 0, mask, counter * defHash.length, defHash.length);
}
while (++counter < (length / defHash.length));
if ((counter * defHash.length) < length)
{
ItoOSP(counter, C);
hash.update(Z, zOff, zLen);
hash.update(C, 0, C.length);
hash.doFinal(hashBuf, 0);
System.arraycopy(hashBuf, 0, mask, counter * defHash.length, mask.length - (counter * defHash.length));
}
return mask;
| public byte[] | processBlock(byte[] in, int inOff, int inLen)
if (forEncryption)
{
return encodeBlock(in, inOff, inLen);
}
else
{
return decodeBlock(in, inOff, inLen);
}
|
|