Files
crypto/src/main/java/net/locusworks/crypto/AES.java
Isaac Parenteau eb5035cb11
All checks were successful
Locusworks Team/crypto/pipeline/head This commit looks good
Updated Libraries
2021-09-14 22:57:25 -05:00

187 lines
6.8 KiB
Java

/*
*
* Project: Crypto, File: AES.java
*
* Copyright 2019 Locusworks LLC.
* All rights reserved. Federal copyright law prohibits unauthorized reproduction by
* any means and imposes fines up to $25,000 for violation. No part of this material
* may be reproduced, transmitted, transcribed, stored in a retrieval system, copied,
* modified, duplicated, adapted or translated into another program language in any
* form or by any means, electronic, mechanical, photocopying, recording, or
* otherwise, without the prior written permission from Locusworks. Locusworks
* affirms that Crypto(R) software and data is subject to United States
* Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive
* Forney TX 75126, (802) 488-0438, for commercial licensing opportunities.
*
* IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY
* LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF
* THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND
* ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
* IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
* ENHANCEMENTS, OR MODIFICATIONS.
*/
package net.locusworks.crypto;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import net.locusworks.crypto.utils.RandomString;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
/**
* AES encryption/decryption class
* This class will encrypt/decrypt data. The encryption key is never known.
* Instead it is is generated by the provided seed. As long as the seed stays the same
* the key will remain the same and the encryption/decryption will work. This
* provides and added security.
* @author Isaac Parenteau
* @version 1.0.0
* @date 02/15/2018
*
*/
public class AES {
private static final String ENCRYPTION_TYPE = "AES";
private static final String ENCRYPTION_ALGORITH = "AES/CBC/PKCS5Padding";
private static final String PROVIDER = "SunJCE";
private static final String ALGORITHM = "SHA1PRNG";
private Cipher cipher;
private SecretKeySpec secretKeySpec;
private IvParameterSpec ivParamSpec;
private AES(byte[] seed) {
initSecureKey(seed);
}
private void initSecureKey(byte[] seed) {
try {
SecureRandom sr = getSecureRandom(seed);
KeyGenerator generator = KeyGenerator.getInstance(ENCRYPTION_TYPE);
generator.init(128, sr);
init(generator.generateKey().getEncoded(), sr);
} catch (Exception ex) {
System.err.println(ex);
throw new IllegalArgumentException("Unable to initalize encryption:", ex);
}
}
/**
* Initializes the secure random object to be the same across all platforms
* with regard to provider and algorithm used
* @param seed Seed to initialize SecureRandom with
* @return SecureRandom object
* @throws NoSuchAlgorithmException thrown when algorithm can't be used
* @throws NoSuchProviderException thrown when the provider cant be found
*/
private static SecureRandom getSecureRandom(byte[] seed) throws NoSuchAlgorithmException {
SecureRandom sr = SecureRandom.getInstance(ALGORITHM);
sr.setSeed(seed);
return sr;
}
/**
* Initialize the aes engine
* @param key secret key to use
* @param sr
*/
private void init(final byte[] key, SecureRandom sr) {
try {
this.cipher = Cipher.getInstance(ENCRYPTION_ALGORITH, PROVIDER);
this.secretKeySpec = new SecretKeySpec(key, ENCRYPTION_TYPE);
this.ivParamSpec = new IvParameterSpec(RandomString.getBytes(16, sr));
} catch (Exception ex) {
System.err.println(ex);
throw new IllegalArgumentException("Unable to initalize encryption:", ex);
}
}
/***
* Encrypt a text string
* @param plainText String to encrypt
* @return encrypted string
*/
public String encrypt(String plainText) {
if (StringUtils.isBlank(plainText)) {
plainText = "";
}
try {
cipher.init(Cipher.ENCRYPT_MODE, this.secretKeySpec, this.ivParamSpec);
byte[] cypherText = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
return new String(Base64.getEncoder().encode(cypherText), StandardCharsets.UTF_8);
} catch (Exception ex) {
throw new IllegalArgumentException(ex.getMessage(), ex);
}
}
/***
* Decrypt an encrypted string
* @param cipherString encrypted string to decrypt
* @return unecrypted string
*/
public String decrypt(String cipherString) {
if (StringUtils.isBlank(cipherString)) {
return "";
}
byte[] cipherText = Base64.getDecoder().decode(cipherString.getBytes(StandardCharsets.UTF_8));
try {
cipher.init(Cipher.DECRYPT_MODE, this.secretKeySpec, this.ivParamSpec);
return new String(cipher.doFinal(cipherText), StandardCharsets.UTF_8);
} catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) {
throw new IllegalArgumentException(e.getMessage(), e);
}
}
public static AES createInstance() {
return createInstance(RandomString.getString(16));
}
public static AES createInstance(byte[] seed) {
return new AES(seed);
}
public static AES createInstance(String seed) {
return createInstance(seed.getBytes(StandardCharsets.UTF_8));
}
public static void main(String[] args) throws NoSuchAlgorithmException, IOException {
Path keyFile = Paths.get("../pseudo-bot/key.bin");
if (!Files.exists(keyFile)) {
throw new IOException("Unable to find key.bin in local directory");
}
byte[] key = IOUtils.toByteArray(Files.newInputStream(keyFile));
AES aes = AES.createInstance(key);
String encrypted = aes.encrypt("pseudobotAdmin2017!");
System.out.println(encrypted);
}
}