
org.slingshot.crypto.bouncycastle.BouncyCastleAESCypher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of CryptoBouncyCastle Show documentation
Show all versions of CryptoBouncyCastle Show documentation
An implementation of the Crypto API that relys on BounceyCastle to perform AES symmteric key encryption.
Contains logic to help construct and lookup keys.
The newest version!
package org.slingshot.crypto.bouncycastle;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Encoder;
import org.bouncycastle.util.encoders.HexEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slingshot.crypto.Cipher;
import org.slingshot.crypto.CryptoException;
/**
* A simple cipher built on top BouncyCastle.
*
* @author rex
*/
public class BouncyCastleAESCypher implements Cipher {
private static final Logger LOGGER = LoggerFactory.getLogger(BouncyCastleAESCypher.class);
private static final Charset CHARSET = Charset.forName("utf16");
private static final Encoder ENCODER = new HexEncoder();
private PaddedBufferedBlockCipher pbbc = new PaddedBufferedBlockCipher(new AESEngine(), new PKCS7Padding());
private final Path keyStoreDir;
private BouncyCastleAESKeyStore keyStore = null;
public BouncyCastleAESCypher(final Path keyStoreDir) {
this.keyStoreDir = keyStoreDir;
keyStore = new BouncyCastleAESKeyStore(keyStoreDir);
}
private KeyParameter fromName(final String name, final boolean makeIfMissing) {
byte[] keyBytes = keyStore.retreiveKey(name);
if (keyBytes == null) {
if (!makeIfMissing) {
throw new CryptoException("Can't decrypt SortedProperties, you would need the right key stored at this location: "
+ name + " in " + keyStoreDir.toString());
} else {
keyStore.createKey(name);
keyBytes = keyStore.retreiveKey(name);
}
}
return new KeyParameter(keyBytes.clone());
}
/**
* {@link Cipher#decrypt(String)}
*
* @param input
* bytes to encrypt
* @return encrypted byte stream
* @throws InvalidCipherTextException
*/
private byte[] encrypt(final byte[] input, final String keyName) throws InvalidCipherTextException {
return processing(input, keyName, true);
}
/**
* {@link Cipher#decrypt(String)}
*
* @param input
* @return decrypted byte stream;
* @throws InvalidCipherTextException
*/
private byte[] decrypt(final byte[] input, final String keyName) throws InvalidCipherTextException {
return processing(input, keyName, false);
}
/**
* Encrypt a string
*
* @param unencrypted
* the unencrypted string
* @return return the encrypted string
*/
@Override
public final String encrypt(final String unencrypted, final String keyName) {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
final byte[] data = encrypt(unencrypted.getBytes(CHARSET), keyName);
ENCODER.encode(data, 0, data.length, stream);
return new String(stream.toByteArray(), Charset.defaultCharset());
} catch (final IOException | InvalidCipherTextException e) {
throw new CryptoException("Could not encrypt string", e);
} finally {
closeQuitely(stream);
}
}
/**
* Decrypt a string
*
* @param encrypted
* the encrypted string
* @return return the decrypted string
*/
@Override
public final String decrypt(final String encrypted, final String keyName) {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
ENCODER.decode(encrypted, stream);
return new String(decrypt(stream.toByteArray(), keyName), CHARSET).trim();
} catch (final DataLengthException dle) {
throw new CryptoException("`" + encrypted + "` could not be decrypted, are you sure this is an encrypted string?", dle);
} catch (final StringIndexOutOfBoundsException sioobe) {
throw new CryptoException("The string `" + encrypted
+ "` is likely not base64 encoded, which means it has never been encrypted,"
+ " are you sure this is an encrypted string?",
sioobe);
} catch (final IOException | InvalidCipherTextException e) {
throw new CryptoException("Could not decrypt string, " + encrypted, e);
} finally {
closeQuitely(stream);
}
}
/**
* Where the bytes are encrypted or decrypted
*
* @param input
* bytes to process
* @param encrypt
* -- whether to encrypt (true), or decrypt (false)
* @return the processed bytes
* @throws InvalidCipherTextException
*/
private byte[] processing(final byte[] input, final String keyName, final boolean encrypt) throws InvalidCipherTextException {
pbbc.init(encrypt, fromName(keyName, encrypt));
final byte[] output = new byte[pbbc.getOutputSize(input.length)];
final int bytesWrittenOut = pbbc.processBytes(input, 0, input.length, output, 0);
pbbc.doFinal(output, bytesWrittenOut);
return output;
}
/**
* Simple utility method used to close...
*
* @param toClose
*/
private void closeQuitely(final Closeable toClose) {
try {
toClose.close();
} catch (final IOException e) {
LOGGER.warn("Error closing stream", e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy