![JAR search and dependency download from the Maven repository](/logo.png)
de.mibos.commons.crypt.Crypt Maven / Gradle / Ivy
/*
* Copyright 2014 Michael Bock
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.mibos.commons.crypt;
import org.apache.commons.io.output.CountingOutputStream;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.WillClose;
import javax.annotation.WillNotClose;
import javax.annotation.concurrent.Immutable;
import javax.annotation.concurrent.ThreadSafe;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidObjectException;
import java.io.ObjectStreamException;
import java.io.OutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import static de.mibos.commons.crypt.BlockMode.CIPHER_BLOCK_CHAIN_MODE;
import static de.mibos.commons.crypt.BlockMode.CIPHER_FEEDBACK_MODE;
import static de.mibos.commons.crypt.BlockMode.OUTPUT_FEEDBACK_MODE;
import static de.mibos.commons.crypt.Padding.NO_PADDING;
import static de.mibos.commons.crypt.Padding.PKCS5_PADDING;
import static java.lang.Math.max;
import static java.lang.reflect.Modifier.isStatic;
import static org.apache.commons.io.IOUtils.closeQuietly;
import static org.apache.commons.io.IOUtils.copyLarge;
import static org.apache.commons.io.IOUtils.readFully;
/**
* A collection of methods for easy to use symmetric encryption and decryption.
*
* You can create your own crypt instances but it is recommended to use the predefined ones.
*
* @author Michael Bock
* @version 1.5
* @since 1.0
* $Id: Crypt.java 89 2014-12-05 00:22:30Z michaels-apps $
*/
@ThreadSafe
@Immutable
public class Crypt implements Serializable {
final private static long serialVersionUID = 2372422428972070135L;
/**
* The encryption algorithm AES with 256 Bits key size. Block mode is CBC, the
* random initialization vector is putted in front of the cipher text. PKCS5 is
* used for padding of the last cipher block.
*
* This is the recommended Crypt for general purpose encryption!
*/
final public static Crypt AES256 = new Crypt("AES", 256, 128);
/**
* The encryption algorithm AES with 192 Bits key size. Block mode is CBC, the
* random initialization vector is putted in front of the cipher text. PKCS5 is
* used for padding of the last cipher block.
*/
final public static Crypt AES192 = new Crypt("AES", 192, 128);
/**
* The encryption algorithm AES with 128 Bits key size. Block mode is CBC, the
* random initialization vector is putted in front of the cipher text. PKCS5 is
* used for padding of the last cipher block.
*/
final public static Crypt AES128 = new Crypt("AES", 128, 128);
/**
* Bruce Schneiers encryption algorithm Blowfish with 256 Bits key size. Block mode is CBC, the
* random initialization vector is putted in front of the cipher text. PKCS5 is
* used for padding of the last cipher block.
*/
final public static Crypt Blowfish256 = new Crypt("Blowfish", 256, 64);
/**
* Bruce Schneiers encryption algorithm Blowfish with 192 Bits key size. Block mode is CBC, the
* random initialization vector is putted in front of the cipher text. PKCS5 is
* used for padding of the last cipher block.
*/
final public static Crypt Blowfish192 = new Crypt("Blowfish", 192, 64);
/**
* Bruce Schneiers encryption algorithm Blowfish with 128 Bits key size. Block mode is CBC, the
* random initialization vector is putted in front of the cipher text. PKCS5 is
* used for padding of the last cipher block.
*/
final public static Crypt Blowfish128 = new Crypt("Blowfish", 128, 64);
/**
* The encryption algorithm DES with 64 Bits key size (effective key size 56 bits!).
* Block mode is CBC, the random initialization vector is putted in front of the
* cipher text. PKCS5 is used for padding of the last cipher block.
*
* This Crypt is generally not recommended!
*/
final public static Crypt DES64 = new Crypt("DES", 64, 64);
/**
* The encryption algorithm Triple-DES with 192 Bits key size (effective key size 168 bits,
* the effective key size for brute force is smaller than 168 bits).
* Block mode is CBC, the random initialization vector is putted in front of the
* cipher text. PKCS5 is used for padding of the last cipher block.
*
* This Crypt is not recommended!
*/
final public static Crypt DES192 = new Crypt("DESede", 192, 64);
/**
* The default algorithm for password hashing
*/
final public static String DEFAULT_PASSWORD_HASHING_ALGORITHM = "SHA-256";
/**
* The default algorithm for block chain mode
*
* @deprecated use {@link de.mibos.commons.crypt.BlockMode#DEFAULT_BLOCK_CHAIN_MODE} instead
*/
@SuppressWarnings("UnusedDeclaration")
final public static String DEFAULT_BLOCK_CHAIN_MODE = BlockMode.DEFAULT_BLOCK_CHAIN_MODE.getShortcut();
/**
* The default algorithm for padding
*
* @deprecated use {@link de.mibos.commons.crypt.Padding#DEFAULT_PADDING_ALGORITHM} instead
*/
@SuppressWarnings("UnusedDeclaration")
final public static String DEFAULT_PADDING_ALGORITHM = Padding.DEFAULT_PADDING_ALGORITHM.getShortcut();
/**
* The default buffer size for IOUtils
*/
final private static int DEFAULT_BUFFER_SIZE = 4 * 1024;
/**
* the encryption algorithm (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
*/
@Nonnull
final private String encryptionAlgorithm;
/**
* the password hashing algorithm for String passwords
*/
@Nonnull
final private String passwordHashingAlgorithm;
/**
* the block mode
*/
@Nonnull
final private BlockMode blockMode;
/**
* the padding
*/
@Nonnull
final private Padding padding;
/**
* the key size in bytes
*/
final private int keySizeInBytes;
/**
* the block size in bytes
*/
final private int blockSizeInBytes;
/**
* the buffer size in bytes for IOUtils operations
*/
final private int bufferSize;
/**
* Constructs a Crypt object with the specified parameters
*
* @param encryptionAlgorithm the encryption algorithm (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
* @param keySize the key size in bits. Compatibility to the encryption algorithm is not checked, so a
* {@link de.mibos.commons.crypt.CryptoInitializationProblem} may be throw later
* @param blockSize the block size in bits. Compatibility to the encryption algorithm is not checked!
* @param passwordHashingAlgorithm the password hashing algorithm for String passwords
* @param blockMode the block encoding mode. Modes other than CBC are not always supported. ECB is strongly discouraged
* @param padding the padding mode (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
* @param bufferSize size of the buffer for io operations
* @since 1.0
* @deprecated use {@link #Crypt(String, int, int, String, BlockMode, Padding, int)} instead
*/
public Crypt(@Nonnull final String encryptionAlgorithm, final int keySize, final int blockSize,
@Nonnull final String passwordHashingAlgorithm, @Nonnull final String blockMode,
@Nonnull final String padding, int bufferSize) {
this(encryptionAlgorithm, keySize, blockSize, passwordHashingAlgorithm, BlockMode.forShortcut(blockMode), Padding.forShortcut(padding), bufferSize);
}
/**
* Constructs a Crypt object with the specified parameters
*
* @param encryptionAlgorithm the encryption algorithm (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
* @param keySize the key size in bits. Compatibility to the encryption algorithm is not checked, so a
* {@link de.mibos.commons.crypt.CryptoInitializationProblem} may be throw later
* @param blockSize the block size in bits. Compatibility to the encryption algorithm is not checked!
* @param passwordHashingAlgorithm the password hashing algorithm for String passwords
* @param blockMode the block encoding mode. Modes other than CBC are not always supported. ECB is strongly discouraged
* @param padding the padding mode (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
* @param bufferSize size of the buffer for io operations
* @since 1.4
*/
public Crypt(@Nonnull final String encryptionAlgorithm, final int keySize, final int blockSize,
@Nonnull final String passwordHashingAlgorithm, @Nonnull final BlockMode blockMode,
@Nonnull final Padding padding, int bufferSize) {
//noinspection ConstantConditions
assert encryptionAlgorithm != null : "encryptionAlgorithm must be not null";
assert keySize > 0 : "keySize must be greater than null";
assert blockSize > 0 : "blockSize must be greater than null";
//noinspection ConstantConditions
assert passwordHashingAlgorithm != null : "passwordHashingAlgorithm must be not null";
//noinspection ConstantConditions
assert blockMode != null : "blockMode must be not null";
//noinspection ConstantConditions
assert padding != null : "padding must be not null";
assert bufferSize > 0 : "bufferSize must be greater than null";
// Check modes and padding for consistence
if (blockMode == CIPHER_BLOCK_CHAIN_MODE) {
if (padding != PKCS5_PADDING)
throw new CryptoInitializationProblem("Block mode CBC is only supported in combination with PKCS5 padding");
} else if (blockMode == CIPHER_FEEDBACK_MODE || blockMode == OUTPUT_FEEDBACK_MODE) {
if (padding != NO_PADDING)
throw new CryptoInitializationProblem("Block modes CFB and OFB are only supported in combination with no padding");
} else {
throw new CryptoInitializationProblem("Unsupported block mode " + blockMode);
}
this.encryptionAlgorithm = encryptionAlgorithm;
this.keySizeInBytes = keySize / 8;
this.blockSizeInBytes = blockSize / 8;
this.passwordHashingAlgorithm = passwordHashingAlgorithm;
this.blockMode = blockMode;
this.padding = padding;
this.bufferSize = bufferSize;
}
/**
* Constructs a Crypt object with the specified parameters
*
* @param encryptionAlgorithm the encryption algorithm (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
* @param keySize the key size in bits. Compatibility to the encryption algorithm is not checked, so a
* {@link de.mibos.commons.crypt.CryptoInitializationProblem} may be throw later
* @param blockSize the block size in bits. Compatibility to the encryption algorithm is not checked!
* @param passwordHashingAlgorithm the password hashing algorithm for String passwords
* @param blockMode the block encoding mode. Modes other than CBC are not always supported. ECB is strongly discouraged
* @param padding the padding mode (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
* @since 1.0
* @deprecated use {@link #Crypt(String, int, int, String, BlockMode, Padding)} instead
*/
public Crypt(@Nonnull final String encryptionAlgorithm, final int keySize, final int blockSize,
@Nonnull final String passwordHashingAlgorithm, @Nonnull final String blockMode,
@Nonnull final String padding) {
this(encryptionAlgorithm, keySize, blockSize, passwordHashingAlgorithm, BlockMode.forShortcut(blockMode), Padding.forShortcut(padding), DEFAULT_BUFFER_SIZE);
}
/**
* Constructs a Crypt object with the specified parameters
*
* @param encryptionAlgorithm the encryption algorithm (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
* @param keySize the key size in bits. Compatibility to the encryption algorithm is not checked, so a
* {@link de.mibos.commons.crypt.CryptoInitializationProblem} may be throw later
* @param blockSize the block size in bits. Compatibility to the encryption algorithm is not checked!
* @param passwordHashingAlgorithm the password hashing algorithm for String passwords
* @param blockMode the block encoding mode. Modes other than CBC are not always supported. ECB is strongly discouraged
* @param padding the padding mode (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
* @since 1.4
*/
public Crypt(@Nonnull final String encryptionAlgorithm, final int keySize, final int blockSize,
@Nonnull final String passwordHashingAlgorithm, @Nonnull final BlockMode blockMode,
@Nonnull final Padding padding) {
this(encryptionAlgorithm, keySize, blockSize, passwordHashingAlgorithm, blockMode, padding, DEFAULT_BUFFER_SIZE);
}
/**
* Constructs a Crypt object with the specified parameters
*
* @param encryptionAlgorithm the encryption algorithm (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
* @param keySize the key size in bits. Compatibility to the encryption algorithm is not checked, so a
* {@link de.mibos.commons.crypt.CryptoInitializationProblem} may be throw later
* @param blockSize the block size in bits. Compatibility to the encryption algorithm is not checked!
* @param blockMode the block encoding mode. Modes other than CBC are not always supported. ECB is unsupported
* @param padding the padding mode (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
* @since 1.0
* @deprecated use {@link #Crypt(String, int, int, BlockMode, Padding)} instead
*/
public Crypt(@Nonnull final String encryptionAlgorithm, final int keySize, final int blockSize,
@Nonnull final String blockMode, @Nonnull final String padding) {
this(encryptionAlgorithm, keySize, blockSize, DEFAULT_PASSWORD_HASHING_ALGORITHM, BlockMode.forShortcut(blockMode), Padding.forShortcut(padding), DEFAULT_BUFFER_SIZE);
}
/**
* Constructs a Crypt object with the specified parameters
*
* @param encryptionAlgorithm the encryption algorithm (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
* @param keySize the key size in bits. Compatibility to the encryption algorithm is not checked, so a
* {@link de.mibos.commons.crypt.CryptoInitializationProblem} may be throw later
* @param blockSize the block size in bits. Compatibility to the encryption algorithm is not checked!
* @param blockMode the block encoding mode. Modes other than CBC are not always supported. ECB is unsupported
* @param padding the padding mode (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
* @since 1.4
*/
public Crypt(@Nonnull final String encryptionAlgorithm, final int keySize, final int blockSize,
@Nonnull final BlockMode blockMode, @Nonnull final Padding padding) {
this(encryptionAlgorithm, keySize, blockSize, DEFAULT_PASSWORD_HASHING_ALGORITHM, blockMode, padding, DEFAULT_BUFFER_SIZE);
}
/**
* Constructs a Crypt object with the specified parameters. For blockMode CBC is used. For padding PKCS5Padding is used
*
* @param encryptionAlgorithm the encryption algorithm (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
* @param keySize the key size in bits. Compatibility to the encryption algorithm is not checked!
* @param blockSize the block size in bits. Compatibility to the encryption algorithm is not checked!
* @param passwordHashingAlgorithm the password hashing algorithm for String passwords
* @since 1.0
*/
public Crypt(@Nonnull final String encryptionAlgorithm, final int keySize, final int blockSize,
@Nonnull final String passwordHashingAlgorithm) {
this(encryptionAlgorithm, keySize, blockSize, passwordHashingAlgorithm, BlockMode.DEFAULT_BLOCK_CHAIN_MODE, Padding.DEFAULT_PADDING_ALGORITHM);
}
/**
* Constructs a Crypt object with the specified parameters. For blockMode CBC is used. For padding PKCS5Padding is used.
* SHA-256 is used as password hashing algorithm.
*
* @param encryptionAlgorithm the encryption algorithm (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html)
* @param keySize the key size in bits. Compatibility to the encryption algorithm is not checked!
* @param blockSize the block size in bits. Compatibility to the encryption algorithm is not checked!
* @since 1.0
*/
public Crypt(@Nonnull final String encryptionAlgorithm, final int keySize, final int blockSize) {
this(encryptionAlgorithm, keySize, blockSize, DEFAULT_PASSWORD_HASHING_ALGORITHM);
}
/**
* Returns the key size in bits
*
* @return the key size in bits
* @since 1.0
*/
public int getKeySize() {
return keySizeInBytes * 8;
}
/**
* Returns the block size in bits
*
* @return the block size in bits
*/
public int getBlockSize() {
return blockSizeInBytes * 8;
}
/**
* Returns the encryption method string
*
* @return the encryption method string
*/
@Nonnull
public String getEncryptionMethod() {
return encryptionAlgorithm + "/" + blockMode.getShortcut() + "/" + padding.getShortcut();
}
/**
* Encrypts all input from the given input stream to the given output stream. Both streams will be closed.
*
* @param input plain text input stream
* @param output cipher text output stream
* @param password password for encryption. The password used actually used will be the hash of this String using
* the specified password hashing algorithm
* @return the number of bytes written to the cipher text output stream
* @throws IOException in case of an underlying {@link java.io.IOException} of the streams
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.0
*/
public long encrypt(@Nonnull @WillClose final InputStream input, @Nonnull @WillClose final OutputStream output,
@Nonnull final CharSequence password) throws IOException {
//noinspection ConstantConditions
assert password != null : "password must be not null";
byte[] passwordBytes;
try {
passwordBytes = getHashedEncryptionKey(password);
} catch (RuntimeException e) {
closeQuietly(input);
closeQuietly(output);
throw e;
}
try {
return internalEncrypt(passwordBytes, input, output);
} finally {
resetPasswordBytes(passwordBytes);
}
}
/**
* Encrypts all input from the given input stream to the given output stream. Both streams will be closed.
*
* @param input plain text input stream
* @param output cipher text output stream
* @param passwordBytes the used password. The length must be compatible to the used encryption algorithm
* @return the number of bytes written to the cipher text output stream
* @throws IOException in case of an underlying {@link java.io.IOException} of the streams
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.0
*/
public long encrypt(@Nonnull @WillClose final InputStream input, @Nonnull @WillClose final OutputStream output,
@Nonnull final byte[] passwordBytes) throws IOException {
//noinspection ConstantConditions
assert input != null : "input must be not null";
//noinspection ConstantConditions
assert output != null : "output must be not null";
//noinspection ConstantConditions
assert passwordBytes != null : "passwordBytes must be not null";
return internalEncrypt(passwordBytes, input, output);
}
/**
* Encrypts the input data and returns the cipher text
*
* @param input plain text
* @param password password for encryption. The password used actually used will be the hash of this String using
* the specified password hashing algorithm
* @return cipher text
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.0
*/
@Nonnull
public byte[] encrypt(@Nonnull final byte[] input, @Nonnull final CharSequence password) {
//noinspection ConstantConditions
assert password != null : "password must be not null";
final byte[] passwordBytes = getHashedEncryptionKey(password);
try {
return encrypt(input, passwordBytes);
} finally {
resetPasswordBytes(passwordBytes);
}
}
/**
* Encrypts the input data and returns the cipher text.
*
* @param input plain text
* @param passwordBytes the used password. The length must be compatible to the used encryption algorithm
* @return cipher text
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.0
*/
@Nonnull
public byte[] encrypt(@Nonnull final byte[] input, @Nonnull final byte[] passwordBytes) {
//noinspection ConstantConditions
assert input != null : "input must be not null";
//noinspection ConstantConditions
assert passwordBytes != null : "passwordBytes must be not null";
final byte[] output = new byte[(int) getMaximumCipherTextLength(input.length)];
int outputSize = internalEncrypt(passwordBytes, input, 0, input.length, output, 0);
assert outputSize == output.length : "must not happen for standard algorithms";
return output;
}
/**
* Encrypts all input from the given byte buffer to the given byte buffer.
* Note that the output {@link java.nio.ByteBuffer} must have a capacity left, which is as least as great
* as a call to {@link #Crypt#getMaximumCipherTextLength(long)} for size of the cipher text returns,
* which may be more than the size of the actual cipher text.
*
* @param input plain text byte buffer
* @param output cipher text byte buffer
* @param password password for encryption. The password used actually used will be the hash of this String using
* the specified password hashing algorithm
* @return cipher text
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.3
*/
public long encrypt(@Nonnull final ByteBuffer input, @Nonnull final ByteBuffer output,
@Nonnull final CharSequence password) {
//noinspection ConstantConditions
assert password != null : "password must be not null";
final byte[] passwordBytes = getHashedEncryptionKey(password);
try {
return encrypt(input, output, passwordBytes);
} finally {
resetPasswordBytes(passwordBytes);
}
}
/**
* Encrypts all input from the given byte buffer to the given byte buffer.
* Note that the output {@link java.nio.ByteBuffer} must have a capacity left, which is as least as great
* as a call to {@link #Crypt#getMaximumCipherTextLength(long)} for size of the cipher text returns,
* which may be more than the size of the actual cipher text.
*
* @param input plain text byte buffer
* @param output cipher text byte buffer
* @param passwordBytes the used password. The length must be compatible to the used encryption algorithm
* @return the number of bytes written to the cipher text byte buffer
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.3
*/
public long encrypt(@Nonnull final ByteBuffer input, @Nonnull final ByteBuffer output,
@Nonnull final byte[] passwordBytes) {
//noinspection ConstantConditions
assert input != null : "input must be not null";
//noinspection ConstantConditions
assert output != null : "output must be not null";
//noinspection ConstantConditions
assert passwordBytes != null : "passwordBytes must be not null";
return internalEncrypt(passwordBytes, input, output);
}
/**
* Decrypts all input from the given input stream to the given outputs stream. Both streams will be closed.
*
* @param input cipher text input stream
* @param output plain text output stream
* @param password password for decryption. The password used actually used will be the hash of this String using
* the specified password hashing algorithm
* @return the number of bytes written to the plain text output stream
* @throws IOException in case of an underlying {@link java.io.IOException} of the streams
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.0
*/
public long decrypt(@Nonnull @WillClose InputStream input, @Nonnull @WillClose OutputStream output,
@Nonnull CharSequence password) throws IOException {
//noinspection ConstantConditions
assert password != null : "password must be not null";
final byte[] passwordBytes;
try {
passwordBytes = getHashedEncryptionKey(password);
} catch (RuntimeException e) {
closeQuietly(input);
closeQuietly(output);
throw e;
}
try {
return internalDecrypt(passwordBytes, input, output);
} finally {
resetPasswordBytes(passwordBytes);
}
}
/**
* Decrypts all input from the given input stream to the given output stream. Both streams will be closed.
*
* @param input cipher text input stream
* @param output plain text output stream
* @param passwordBytes the used password. The length must be compatible to the used encryption algorithm
* @return the number of bytes written to the plain text output stream
* @throws IOException in case of an underlying {@link java.io.IOException} of the streams
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.0
*/
public long decrypt(@Nonnull @WillClose InputStream input, @Nonnull @WillClose OutputStream output,
@Nonnull final byte[] passwordBytes) throws IOException {
//noinspection ConstantConditions
assert input != null : "input must be not null";
//noinspection ConstantConditions
assert output != null : "output must be not null";
//noinspection ConstantConditions
assert passwordBytes != null : "passwordBytes must be not null";
return internalDecrypt(passwordBytes, input, output);
}
/**
* Decrypts the input data and returns the plain text
*
* @param input cipher text
* @param password password for decryption. The password used actually used will be the hash of this String using
* the specified password hashing algorithm
* @return plain text
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.0
*/
@Nonnull
public byte[] decrypt(@Nonnull final byte[] input, @Nonnull final CharSequence password) {
//noinspection ConstantConditions
assert password != null : "password must be not null";
final byte[] passwordBytes = getHashedEncryptionKey(password);
try {
return decrypt(input, passwordBytes);
} finally {
resetPasswordBytes(passwordBytes);
}
}
/**
* Decrypts the input data and returns the plain text
*
* @param input cipher text
* @param passwordBytes the used password. The length must be compatible to the used encryption algorithm
* @return plain text
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.0
*/
@Nonnull
public byte[] decrypt(@Nonnull final byte[] input, @Nonnull final byte[] passwordBytes) {
//noinspection ConstantConditions
assert input != null : "input must be not null";
//noinspection ConstantConditions
assert passwordBytes != null : "passwordBytes must be not null";
final byte[] output = new byte[(int) getMaximumPlainTextLength(input.length)];
int outputSize = internalDecrypt(passwordBytes, input, 0, input.length, output, 0);
if (outputSize < output.length) {
final byte[] result = new byte[outputSize];
System.arraycopy(output, 0, result, 0, outputSize);
return result;
} else {
return output;
}
}
/**
* Decrypts all input from the given byte buffer to the given byte buffer.
* Note that the output {@link java.nio.ByteBuffer} must have a capacity left, which is as least as great
* as a call to {@link #Crypt#getMaximumPlainTextLength(long)} for size of the plain text returns,
* which may be more than the size of the actual plain text.
*
* @param input cipher text byte buffer
* @param output test text byte buffer
* @param password password for decryption. The password used actually used will be the hash of this String using
* the specified password hashing algorithm
* @return cipher text
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @throws CryptoBufferOverflowException not enough bytes in output
* @throws CryptoInvalidCipherTextException invalid cipher text
* @since 1.3
*/
public long decrypt(@Nonnull final ByteBuffer input, @Nonnull final ByteBuffer output,
@Nonnull final CharSequence password) {
//noinspection ConstantConditions
assert password != null : "password must be not null";
final byte[] passwordBytes = getHashedEncryptionKey(password);
try {
return decrypt(input, output, passwordBytes);
} finally {
resetPasswordBytes(passwordBytes);
}
}
/**
* Decrypts all input from the given byte buffer to the given byte buffer.
* Note that the output {@link java.nio.ByteBuffer} must have a capacity left, which is as least as great
* as a call to {@link #Crypt#getMaximumPlainTextLength(long)} for size of the plain text returns,
* which may be more than the size of the actual plain text.
*
* @param input cipher text byte buffer
* @param output test text byte buffer
* @param passwordBytes the used password. The length must be compatible to the used encryption algorithm
* @return the number of bytes written to the cipher text byte buffer
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @throws CryptoBufferOverflowException not enough bytes in output
* @throws CryptoInvalidCipherTextException invalid cipher text
* @since 1.3
*/
public long decrypt(@Nonnull final ByteBuffer input, @Nonnull final ByteBuffer output,
@Nonnull final byte[] passwordBytes) {
//noinspection ConstantConditions
assert input != null : "input must be not null";
//noinspection ConstantConditions
assert output != null : "output must be not null";
//noinspection ConstantConditions
assert passwordBytes != null : "passwordBytes must be not null";
return internalDecrypt(passwordBytes, input, output);
}
/**
* Creates an input stream for this Crypt for decryption
* This is simply an extension to the standard {@link javax.crypto.CipherInputStream}, which
* additionally adds the initialization vector
*
* @param input the cipher input stream
* @param password the password
* @throws IOException {@link java.io.IOException} if failing to read the initialization vector
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.3
*/
public CryptInputStream getInputStream(@Nonnull final InputStream input, @Nonnull final CharSequence password) throws IOException {
return new CryptInputStream(this, input, password);
}
/**
* Creates an input stream for this Crypt for decryption
* This is simply an extension to the standard {@link javax.crypto.CipherInputStream}, which
* additionally adds the initialization vector
*
* @param input the cipher input stream
* @param passwordBytes the password bytes
* @throws IOException {@link java.io.IOException} if failing to read the initialization vector
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.3
*/
public CryptInputStream getInputStream(@Nonnull final InputStream input, @Nonnull final byte[] passwordBytes) throws IOException {
return new CryptInputStream(this, input, passwordBytes);
}
/**
* Creates an input stream for this Crypt for encryption
* This is simply an extension to the standard {@link javax.crypto.CipherInputStream}, which
* provides the initialization vector as input
*
* @param input the cipher input stream
* @param password the password
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.5
*/
public PlainInputStream getPlainInputStream(@Nonnull final InputStream input, @Nonnull final CharSequence password) {
return new PlainInputStream(this, input, password);
}
/**
* Creates an input stream for this Crypt for encryption
* This is simply an extension to the standard {@link javax.crypto.CipherInputStream}, which
* provides the initialization vector as input
*
* @param input the cipher input stream
* @param passwordBytes the password bytes
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.5
*/
public PlainInputStream getPlainInputStream(@Nonnull final InputStream input, @Nonnull final byte[] passwordBytes) {
return new PlainInputStream(this, input, passwordBytes);
}
/**
* Creates an output stream for this Crypt.
* This is simply an extension to the standard {@link javax.crypto.CipherOutputStream}, which
* writes the initialization vector in this method.
* Please ensure that close is always called explicitly for this stream object. Failing to do so will result in
* missing cipher text bytes.
*
* @param output the cipher output stream
* @param password the password
* @throws IOException {@link java.io.IOException} if failing to write the initialization vector
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.3
*/
public CryptOutputStream getOutputStream(@Nonnull final OutputStream output, @Nonnull final CharSequence password) throws IOException {
return new CryptOutputStream(this, output, password);
}
/**
* Creates an output stream for this Crypt.
* This is simply an extension to the standard {@link javax.crypto.CipherOutputStream}, which
* writes the initialization vector in this method.
* Please ensure that close is always called explicitly for this stream object. Failing to do so will result in
* missing cipher text bytes.
*
* @param output the cipher output stream
* @param passwordBytes the password bytes
* @throws IOException {@link java.io.IOException} if failing to write the initialization vector
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @since 1.3
*/
public CryptOutputStream getOutputStream(@Nonnull final OutputStream output, @Nonnull final byte[] passwordBytes) throws IOException {
return new CryptOutputStream(this, output, passwordBytes);
}
/**
* Returns the maximum bytes needed for the cipher text for a given plain text length
*
* @param plainTextLength plain text length
* @return maximum bytes needed for the cipher text
* @since 1.4
*/
public long getMaximumCipherTextLength(final long plainTextLength) {
if (padding == NO_PADDING) {
return plainTextLength + blockSizeInBytes;
} else {
return plainTextLength + 2 * blockSizeInBytes - (plainTextLength % blockSizeInBytes);
}
}
/**
* Returns the maximum bytes needed for the plain text for a given cipher text length
*
* @param cipherTextLength cipher text length
* @return maximum bytes needed for the plain text
* @since 1.4
*/
@SuppressWarnings("WeakerAccess")
public long getMaximumPlainTextLength(final long cipherTextLength) {
return max(cipherTextLength - blockSizeInBytes, 0);
}
/**
* Encrypts all input from the given input stream to the given output stream. Both streams will be closed.
*
* @param passwordBytes the used password. The length must be compatible to the used encryption algorithm
* @param input plain text input stream
* @param output cipher text output stream
* @return the number of bytes written to the cipher text output stream
* @throws IOException in case of an underlying {@link java.io.IOException} of the streams
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
*/
private long internalEncrypt(@Nonnull final byte[] passwordBytes, @Nonnull @WillClose final InputStream input,
@Nonnull @WillClose final OutputStream output) throws IOException {
final Cipher cipher;
final byte[] iv;
try {
cipher = getEncryptionCipher(passwordBytes);
iv = cipher.getIV();
} catch (RuntimeException e) {
closeQuietly(input);
closeQuietly(output);
throw e;
}
final CountingOutputStream countingOutputStream = new CountingOutputStream(output);
final CipherOutputStream cipherOutputStream = new CipherOutputStream(countingOutputStream, cipher);
try {
countingOutputStream.write(iv);
copyLarge(input, cipherOutputStream, new byte[bufferSize]);
} finally {
closeQuietly(input);
closeQuietly(cipherOutputStream);
}
return countingOutputStream.getByteCount();
}
/**
* Encrypts all input from the given byte array to the given byte array
*
* @param passwordBytes the used password. The length must be compatible to the used encryption algorithm
* @param input plain text byte array
* @param inputOffset offset in the plain text array
* @param inputLength length of the plain text
* @param output cipher text byte array
* @param outputOffset offset in the cipher text array
* @return the number of bytes written to the cipher text byte array
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
*/
@SuppressWarnings("SameParameterValue")
private int internalEncrypt(@Nonnull final byte[] passwordBytes,
@Nonnull final byte[] input, final int inputOffset, final int inputLength,
@Nonnull final byte[] output, final int outputOffset) {
try {
final Cipher cipher = getEncryptionCipher(passwordBytes);
final byte[] iv = cipher.getIV();
System.arraycopy(iv, 0, output, outputOffset, iv.length);
return iv.length + cipher.doFinal(input, inputOffset, inputLength, output, outputOffset + iv.length);
} catch (ShortBufferException e) {
throw new CryptoBufferOverflowException("output buffer too small", e);
} catch (IllegalBlockSizeException | BadPaddingException e) {
throw new CryptoInitializationProblem(getEncryptionMethod() + " encryption or padding not available on encrypt?", e);
}
}
/**
* Encrypts all input from the given byte buffer to the give byte buffer
*
* @param passwordBytes the used password. The length must be compatible to the used encryption algorithm
* @param input plain text byte buffer
* @param output cipher text byte buffer
* @return the number of bytes written to the cipher text byte buffer
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
*/
private long internalEncrypt(@Nonnull final byte[] passwordBytes, @Nonnull final ByteBuffer input,
@Nonnull final ByteBuffer output) {
try {
final Cipher cipher = getEncryptionCipher(passwordBytes);
final byte[] iv = cipher.getIV();
output.put(iv);
return iv.length + cipher.doFinal(input, output);
} catch (ShortBufferException e) {
throw new CryptoBufferOverflowException("output buffer too small", e);
} catch (IllegalBlockSizeException | BadPaddingException e) {
throw new CryptoInitializationProblem(getEncryptionMethod() + " encryption or padding not available on encrypt?", e);
}
}
/**
* Decrypts all input from the given input stream to the given output stream. Both streams will be closed.
*
* @param passwordBytes the used password. The length must be compatible to the used encryption algorithm
* @param input cipher text input stream
* @param output plain text output stream
* @return the number of bytes written to the plain text output stream
* @throws IOException in case of an underlying {@link java.io.IOException} of the streams
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
*/
private long internalDecrypt(@Nonnull final byte[] passwordBytes, @Nonnull @WillClose final InputStream input,
@Nonnull @WillClose OutputStream output) throws IOException {
final Cipher cipher;
try {
final byte[] iv = getIV(input);
cipher = getDecryptionCipher(passwordBytes, iv);
} catch (RuntimeException | IOException e) {
closeQuietly(input);
closeQuietly(output);
throw e;
}
final CipherInputStream cipherInputStream = new CipherInputStream(input, cipher);
final CountingOutputStream countingOutputStream = new CountingOutputStream(output);
try {
copyLarge(cipherInputStream, countingOutputStream, new byte[bufferSize]);
} finally {
closeQuietly(cipherInputStream);
closeQuietly(countingOutputStream);
}
return countingOutputStream.getByteCount();
}
/**
* Decrypts all input from the given byte array to the given byte array
*
* @param passwordBytes the used password. The length must be compatible to the used encryption algorithm
* @param input cipher text byte array
* @param inputOffset offset in the cipher text array
* @param inputLength length of the cipher text
* @param output plain text byte array
* @param outputOffset offset in the plain text array
* @return the number of bytes written to the plain text byte array
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
*/
@SuppressWarnings("SameParameterValue")
private int internalDecrypt(@Nonnull final byte[] passwordBytes,
@Nonnull final byte[] input, final int inputOffset, final int inputLength,
@Nonnull final byte[] output, final int outputOffset) {
try {
final byte[] iv = getIV(input, inputOffset);
final Cipher cipher = getDecryptionCipher(passwordBytes, iv);
return cipher.doFinal(input, inputOffset + iv.length, inputLength - iv.length, output, outputOffset);
} catch (ShortBufferException e) {
throw new CryptoBufferOverflowException("output buffer too small", e);
} catch (IllegalBlockSizeException e) {
throw new CryptoInvalidCipherTextException("input must be a multiple of the block size", e);
} catch (BadPaddingException e) {
throw new CryptoInvalidCipherTextException("invalid padding", e);
}
}
/**
* Decrypts all input from the given byte buffer to the give byte buffer
*
* @param passwordBytes the used password. The length must be compatible to the used encryption algorithm
* @param input cipher text byte buffer
* @param output plain text byte buffer
* @return the number of bytes written to the cipher text byte buffer
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
* @throws CryptoBufferOverflowException not enough bytes in output
* @throws CryptoInvalidCipherTextException invalid h text
*/
private long internalDecrypt(@Nonnull final byte[] passwordBytes, @Nonnull final ByteBuffer input,
@Nonnull final ByteBuffer output) {
try {
final byte[] iv = getIV(input);
final Cipher cipher = getDecryptionCipher(passwordBytes, iv);
return cipher.doFinal(input, output);
} catch (ShortBufferException e) {
throw new CryptoBufferOverflowException("output buffer too small", e);
} catch (IllegalBlockSizeException e) {
throw new CryptoInvalidCipherTextException("input must be a multiple of the block size", e);
} catch (BadPaddingException e) {
throw new CryptoInvalidCipherTextException("invalid padding", e);
}
}
/**
* Creates and initializes the Cipher object for encryption
*
* @param passwordBytes the used password. The length must be compatible to the used encryption algorithm
* @return the cipher object for this crypt object
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
*/
@Nonnull
Cipher getEncryptionCipher(@Nonnull final byte[] passwordBytes) {
final Cipher cipher = getCipher();
initCipher(cipher, passwordBytes, Cipher.ENCRYPT_MODE, null);
return cipher;
}
/**
* Creates and initializes the Cipher object for decryption
*
* @param passwordBytes the used password. The length must be compatible to the used encryption algorithm
* @param iv the initialization vector
* @return the cipher object for this crypt object
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
*/
@Nonnull
Cipher getDecryptionCipher(@Nonnull final byte[] passwordBytes, @Nonnull byte[] iv) {
final Cipher cipher = getCipher();
initCipher(cipher, passwordBytes, Cipher.DECRYPT_MODE, iv);
return cipher;
}
/**
* Reads the initialization vector from an input stream
*
* @param input the stream
* @return the initialization vector
*/
byte[] getIV(@Nonnull @WillNotClose final InputStream input) throws IOException {
try {
final byte[] iv = new byte[blockSizeInBytes];
readFully(input, iv);
return iv;
} catch (EOFException e) {
throw new CryptoInvalidCipherTextException("not enough bytes for initialization vector", e);
}
}
/**
* Reads the initialization vector from a byte buffer
*
* @param input the byte buffer
* @return the initialization vector
*/
private byte[] getIV(@Nonnull final ByteBuffer input) {
try {
final byte[] iv = new byte[blockSizeInBytes];
input.get(iv);
return iv;
} catch (BufferUnderflowException e) {
throw new CryptoInvalidCipherTextException("not enough bytes for initialization vector", e);
}
}
/**
* Reads the initialization vector from a byte array
*
* @param input the byte array
* @return the initialization vector
*/
private byte[] getIV(@Nonnull final byte[] input, final int offset) {
try {
final byte[] iv = new byte[blockSizeInBytes];
System.arraycopy(input, offset, iv, 0, blockSizeInBytes);
return iv;
} catch (IndexOutOfBoundsException e) {
throw new CryptoInvalidCipherTextException("not enough bytes for initialization vector", e);
}
}
/**
* Creates the cipher object
*
* @return the cipher object for this crypt object
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
*/
@Nonnull
private Cipher getCipher() {
try {
return Cipher.getInstance(getEncryptionMethod());
} catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
throw new CryptoInitializationProblem(getEncryptionMethod() + " encryption or padding not available", e);
}
}
/**
* Initializes the cipher object
*
* @param cipher the cipher object
* @param passwordBytes the password bytes
* @param mode the cipher mode (encrypt or decrypt)
* @param iv the initialization vector (only needed for decryption)
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
*/
private void initCipher(@Nonnull final Cipher cipher, @Nonnull final byte[] passwordBytes, final int mode,
@CheckForNull final byte[] iv) {
try {
final SecretKeySpec keySpec = new SecretKeySpec(passwordBytes, encryptionAlgorithm);
if (iv != null) {
cipher.init(mode, keySpec, new IvParameterSpec(iv));
} else {
cipher.init(mode, keySpec);
}
if (cipher.getBlockSize() != blockSizeInBytes) {
throw new CryptoInitializationProblem(
getEncryptionMethod() + " calculated block size " + cipher.getBlockSize() + " does not match expected blocksize " + blockSizeInBytes);
}
} catch (InvalidAlgorithmParameterException e) {
throw new CryptoInitializationProblem(getEncryptionMethod() + " initialization vector not allowed?", e);
} catch (InvalidKeyException e) {
throw new CryptoInitializationProblem(
getEncryptionMethod()
+ " invalid key size, you probably need to replace the security policies in $JAVA_HOME/jre/lib/security, "
+ "see here http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html",
e);
}
}
/**
* Hashes a password string
*
* @param password the string password
* @return the hashed password bytes
* @throws CryptoInitializationProblem in case of a {@link de.mibos.commons.crypt.CryptoInitializationProblem} problem
*/
@Nonnull
public byte[] getHashedEncryptionKey(@Nonnull final CharSequence password) {
try {
final MessageDigest md = MessageDigest.getInstance(passwordHashingAlgorithm);
if (password instanceof CharBuffer) {
md.update(StandardCharsets.UTF_8.encode((CharBuffer) password));
} else {
md.update(StandardCharsets.UTF_8.encode(password.toString()));
}
final byte[] digest = md.digest();
md.reset();
if (digest.length == keySizeInBytes) {
return digest;
} else if (digest.length > keySizeInBytes) {
final byte[] passwordBytes = new byte[keySizeInBytes];
System.arraycopy(digest, 0, passwordBytes, 0, keySizeInBytes);
resetPasswordBytes(digest);
return passwordBytes;
} else {
throw new CryptoInitializationProblem("Hashing algorithm " + passwordHashingAlgorithm
+ " produces not enough bytes for key, required " + (keySizeInBytes * 8) + " bits, provided only " +
(digest.length * 8) + " bits");
}
} catch (NoSuchAlgorithmException e) {
throw new CryptoInitializationProblem("Hashing algorithm " + passwordHashingAlgorithm + " not available", e);
}
}
/**
* Prevents password bytes from hanging around in memory by overwriting with zero bytes
*
* @param passwordBytes the password bytes to reset
*/
void resetPasswordBytes(@Nonnull final byte[] passwordBytes) {
Arrays.fill(passwordBytes, (byte) 0);
}
/**
* String description of this Crypt
*
* @return String description of this Crypt
* @since 1.4
*/
@Override
public String toString() {
return "Crypt{" +
"encryptionAlgorithm='" + encryptionAlgorithm + '\'' +
", passwordHashingAlgorithm='" + passwordHashingAlgorithm + '\'' +
", blockMode=" + blockMode +
", padding=" + padding +
", keySize=" + (keySizeInBytes * 8) +
", blockSize=" + (blockSizeInBytes * 8) +
", bufferSize=" + bufferSize +
'}';
}
/**
* Is this Crypt equal to the given object
*
* @param other the object to compare
* @return true, if this Crypt is equal to the given object
* @since 1.4
*/
@Override
public boolean equals(@CheckForNull final Object other) {
if (this == other) {
return true;
}
if (other == null || getClass() != other.getClass()) {
return false;
}
final Crypt otherCrypt = (Crypt) other;
return blockSizeInBytes == otherCrypt.blockSizeInBytes &&
bufferSize == otherCrypt.bufferSize &&
keySizeInBytes == otherCrypt.keySizeInBytes &&
blockMode == otherCrypt.blockMode &&
padding == otherCrypt.padding &&
encryptionAlgorithm.equalsIgnoreCase(otherCrypt.encryptionAlgorithm) &&
passwordHashingAlgorithm.equalsIgnoreCase(otherCrypt.passwordHashingAlgorithm);
}
/**
* The hash code of this crypt
*
* @return the hash code of this crypt
* @since 1.4
*/
@Override
public int hashCode() {
int result = encryptionAlgorithm.hashCode();
result = 31 * result + passwordHashingAlgorithm.hashCode();
result = 31 * result + blockMode.hashCode();
result = 31 * result + padding.hashCode();
result = 31 * result + keySizeInBytes;
result = 31 * result + blockSizeInBytes;
result = 31 * result + bufferSize;
return result;
}
/**
* For the static instances, the same instance will be returned
*
* @return the static instance, if found
* @throws ObjectStreamException error accessing static instances
* @since 1.4
*/
@Nonnull
private Object readResolve() throws ObjectStreamException {
final Field[] fields = getClass().getFields();
for (Field field : fields) {
try {
if (isStatic(field.getModifiers()) && this.equals(field.get(null))) {
return field.get(null);
}
} catch (IllegalAccessException e) {
throw new InvalidObjectException(e.getMessage());
}
}
return this;
}
/**
* Returns the encryption algorithm
*
* @return the encryption algorithm
* @since 1.4
*/
@Nonnull
public String getEncryptionAlgorithm() {
return encryptionAlgorithm;
}
/**
* Returns the password hashing algorithm
*
* @return the password hashing algorithm
* @since 1.4
*/
@Nonnull
public String getPasswordHashingAlgorithm() {
return passwordHashingAlgorithm;
}
/**
* Returns the block mode
*
* @return the block mode
* @since 1.4
*/
@Nonnull
public BlockMode getBlockMode() {
return blockMode;
}
/**
* Returns the padding
*
* @return the padding
* @since 1.4
*/
@Nonnull
public Padding getPadding() {
return padding;
}
/**
* Returns the buffer size
*
* @return the buffer size
* @since 1.4
*/
public int getBufferSize() {
return bufferSize;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy