All checks were successful
Locusworks Team/crypto/pipeline/head This commit looks good
187 lines
6.8 KiB
Java
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);
|
|
}
|
|
|
|
}
|