BlockCipherBasepublic abstract class BlockCipherBase extends Cipher Class providing common functionality for DES ciphers. |
Fields Summary |
---|
private int | blockSizeBlock size. | protected int | modeENCRYPT or DECRYPT. | protected Padder | padderThe padder. | protected byte[] | holdDataContains the data that is not encrypted or decrypted yet. | protected int | holdCountThe holding buffer counter. | protected boolean | isUpdatedIndicates if this cipher object has been updated or not. | private byte[] | savedHoldDataSaved state variable. | private int | savedHoldCountSaved state variable. | private boolean | savedIsUpdatedSaved state variable. | protected byte[] | IVInitial vector. | private boolean | keepLastBlockTrue in decryption with padder mode. |
Constructors Summary |
---|
protected BlockCipherBase(int blockSize)Constructor.
this.blockSize = blockSize;
holdData = new byte[blockSize];
mode = MODE_UNINITIALIZED;
|
Methods Summary |
---|
public int | doFinal(byte[] in, int offset, int len, byte[] out, int outOffset)Encrypts or decrypts data in a single-part operation, or finishes a
multiple-part operation. The data is encrypted or decrypted,
depending on how this cipher was initialized.
Util.checkBounds(in, offset, len, out, outOffset);
if (mode == MODE_UNINITIALIZED) {
throw new IllegalStateException();
}
if (len == 0 && ! isUpdated) {
return 0;
}
boolean encrypt = mode == Cipher.ENCRYPT_MODE;
// calculate the size of the possible out buffer
int expectedSize = len + holdCount;
int delta = expectedSize % blockSize;
if (delta != 0) {
if (! encrypt || (encrypt && padder == null)) {
throw new IllegalBlockSizeException();
}
expectedSize += blockSize - delta;
} else
if (encrypt && padder != null) {
expectedSize += blockSize;
}
int excess = outOffset + expectedSize - out.length;
// padder may remove up to blockSize bytes after decryption
if (excess > (keepLastBlock ? blockSize : 0)) {
throw new ShortBufferException();
}
if (keepLastBlock && excess > 0) {
// after unpadding data may not fit into output buffer
saveState();
}
int counter = update(in, offset, len, out, outOffset);
if (padder != null) {
if (encrypt) {
if (padder.pad(holdData, holdCount) != 0) {
processBlock(out, outOffset + counter);
counter += blockSize;
}
} else {
byte[] lastBlock = new byte[blockSize];
processBlock(lastBlock, 0);
int tail = blockSize - padder.unPad(lastBlock, blockSize);
if (outOffset + counter + tail > out.length) {
restoreState();
throw new ShortBufferException();
}
System.arraycopy(lastBlock, 0,
out, outOffset + counter, tail);
counter += tail;
}
}
holdCount = 0;
return counter;
| protected void | doInit(int mode, java.lang.String keyAlgorithm, Key key, boolean needIV, CryptoParameter params)Initializes a cipher object with the key and sets
encryption or decryption mode.
byte[] IV;
if (needIV) {
if (params == null) {
if (mode == Cipher.DECRYPT_MODE) {
throw new InvalidAlgorithmParameterException();
}
IV = new byte[blockSize];
} else {
if (! (params instanceof IvParameter)) {
throw new InvalidAlgorithmParameterException();
}
IV = Util.cloneArray(((IvParameter)params).getIV());
if (IV.length != blockSize) {
throw new InvalidAlgorithmParameterException();
}
}
} else {
if (params != null) {
throw new InvalidAlgorithmParameterException();
}
IV = null;
}
if (!(key instanceof SecretKey &&
keyAlgorithm.equals(key.getAlgorithm()))) {
throw new InvalidKeyException();
}
initKey(key.getEncoded(), mode);
holdCount = 0;
isUpdated = false;
this.mode = mode;
this.IV = IV;
keepLastBlock = mode == Cipher.DECRYPT_MODE && padder != null;
| public byte[] | getIV()Returns the initialization vector (IV) in a new buffer.
This is useful in the case where a random IV was created.
return IV == null ? null : Util.cloneArray(IV);
| abstract void | initKey(byte[] data, int mode)Initializes key.
| abstract void | processBlock(byte[] out, int offset)Depending on the mode, either encrypts or decrypts data block.
| protected void | restoreState()Restores cipher state.
holdCount = savedHoldCount;
holdData = savedHoldData;
isUpdated = savedIsUpdated;
| protected void | saveState()Saves cipher state.
savedHoldCount = holdCount;
savedHoldData = holdCount == 0 ?
holdData :
Util.cloneArray(holdData);
savedIsUpdated = isUpdated;
| protected void | setPadding(java.lang.String padding)Sets the padder.
if (padding.equals("") || padding.equals("PKCS5PADDING")) {
padder = new PKCS5Padding(blockSize);
} else if (!padding.equals("NOPADDING")) {
throw new NoSuchPaddingException(padding);
}
| public int | update(byte[] in, int offset, int len, byte[] out, int outOffset)Continues a multiple-part encryption or decryption operation
(depending on how this cipher was initialized), processing another data
part.
Util.checkBounds(in, offset, len, out, outOffset);
if (mode == MODE_UNINITIALIZED) {
throw new IllegalStateException();
}
if (len == 0) {
return 0;
}
if (((holdCount + len) / blockSize -
(keepLastBlock ? 1 : 0)) * blockSize >
out.length - outOffset) {
throw new ShortBufferException();
}
isUpdated = true;
if (in == out) {
in = new byte[len];
System.arraycopy(out, offset, in, 0, len);
offset = 0;
}
int counter = 0;
while (true) {
int got;
System.arraycopy(in, offset, holdData, holdCount,
got = Math.min(blockSize - holdCount, len));
offset += got;
len -= got;
holdCount += got;
if (holdCount < blockSize || (len == 0 && keepLastBlock)) {
return counter;
}
processBlock(out, outOffset);
counter += blockSize;
outOffset += blockSize;
}
|
|