All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dorkbox.util.crypto.CryptoAES Maven / Gradle / Ivy

There is a newer version: 1.48
Show newest version
/*
 * Copyright 2010 dorkbox, llc
 *
 * Licensed 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 dorkbox.util.crypto;

import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.slf4j.Logger;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * AES crypto functions
 */
@SuppressWarnings({"Duplicates"})
public final
class CryptoAES {
    private static final int ivSize = 16;

    /**
     * AES encrypts data with a specified key.
     *
     * @param aesIV
     *                 must be a nonce (unique value) !!
     * @param logger
     *                 may be null, if no log output is necessary
     *
     * @return empty byte[] if error
     */
    public static
    byte[] encryptWithIV(GCMBlockCipher aesEngine, byte[] aesKey, byte[] aesIV, byte[] data, Logger logger) {
        byte[] encryptAES = encrypt(aesEngine, aesKey, aesIV, data, logger);

        int length = encryptAES.length;

        byte[] out = new byte[length + ivSize];
        System.arraycopy(aesIV, 0, out, 0, ivSize);
        System.arraycopy(encryptAES, 0, out, ivSize, length);

        return out;
    }

    /**
     * CONVENIENCE METHOD ONLY - DO NOT USE UNLESS YOU HAVE TO
     * 

* Use GCM instead, as it's an authenticated cipher (and "regular" AES is not). This prevents tampering with the blocks of encrypted * data. *

* AES encrypts data with a specified key. * * @param aesIV * must be a nonce (unique value) !! * @param logger * may be null, if no log output is necessary * * @return empty byte[] if error */ @Deprecated public static byte[] encryptWithIV(BufferedBlockCipher aesEngine, byte[] aesKey, byte[] aesIV, byte[] data, Logger logger) { byte[] encryptAES = encrypt(aesEngine, aesKey, aesIV, data, logger); int length = encryptAES.length; byte[] out = new byte[length + ivSize]; System.arraycopy(aesIV, 0, out, 0, ivSize); System.arraycopy(encryptAES, 0, out, ivSize, length); return out; } /** * AES encrypts data with a specified key. * * @param aesIV * must be a nonce (unique value) !! * @param logger * may be null, if no log output is necessary * * @return true if successful */ public static boolean encryptStreamWithIV(GCMBlockCipher aesEngine, byte[] aesKey, byte[] aesIV, InputStream in, OutputStream out, Logger logger) { try { out.write(aesIV); } catch (IOException e) { if (logger != null) { logger.error("Unable to perform AES cipher.", e); } return false; } return encryptStream(aesEngine, aesKey, aesIV, in, out, logger); } /** * CONVENIENCE METHOD ONLY - DO NOT USE UNLESS YOU HAVE TO *

* Use GCM instead, as it's an authenticated cipher (and "regular" AES is not). This prevents tampering with the blocks of encrypted * data. *

* AES encrypts data with a specified key. * * @param aesIV * must be a nonce (unique value) !! * @param logger * may be null, if no log output is necessary * * @return true if successful */ @Deprecated public static boolean encryptStreamWithIV(BufferedBlockCipher aesEngine, byte[] aesKey, byte[] aesIV, InputStream in, OutputStream out, Logger logger) { try { out.write(aesIV); } catch (IOException e) { if (logger != null) { logger.error("Unable to perform AES cipher.", e); } return false; } return encryptStream(aesEngine, aesKey, aesIV, in, out, logger); } /** * AES encrypts data with a specified key. * * @param aesIV * must be a nonce (unique value) !! * @param logger * may be null, if no log output is necessary * * @return empty byte[] if error */ public static byte[] encrypt(GCMBlockCipher aesEngine, byte[] aesKey, byte[] aesIV, byte[] data, Logger logger) { int length = data.length; CipherParameters aesIVAndKey = new ParametersWithIV(new KeyParameter(aesKey), aesIV); return encrypt(aesEngine, aesIVAndKey, data, length, logger); } /** * AES encrypts data with a specified key. * * @param logger * may be null, if no log output is necessary * * @return length of encrypted data, -1 if there was an error. */ public static byte[] encrypt(GCMBlockCipher aesEngine, CipherParameters aesIVAndKey, byte[] data, int length, Logger logger) { aesEngine.reset(); aesEngine.init(true, aesIVAndKey); int minSize = aesEngine.getOutputSize(length); byte[] outArray = new byte[minSize]; int actualLength = aesEngine.processBytes(data, 0, length, outArray, 0); try { actualLength += aesEngine.doFinal(outArray, actualLength); } catch (Exception e) { if (logger != null) { logger.error("Unable to perform AES cipher.", e); } return new byte[0]; } if (outArray.length == actualLength) { return outArray; } else { byte[] result = new byte[actualLength]; System.arraycopy(outArray, 0, result, 0, result.length); return result; } } /** * CONVENIENCE METHOD ONLY - DO NOT USE UNLESS YOU HAVE TO *

* Use GCM instead, as it's an authenticated cipher (and "regular" AES is not). This prevents tampering with the blocks of encrypted * data. *

* AES encrypts data with a specified key. * * @param aesIV * must be a nonce (unique value) !! * @param logger * may be null, if no log output is necessary * * @return empty byte[] if error */ @Deprecated public static byte[] encrypt(BufferedBlockCipher aesEngine, byte[] aesKey, byte[] aesIV, byte[] data, Logger logger) { int length = data.length; CipherParameters aesIVAndKey = new ParametersWithIV(new KeyParameter(aesKey), aesIV); aesEngine.reset(); aesEngine.init(true, aesIVAndKey); int minSize = aesEngine.getOutputSize(length); byte[] outBuf = new byte[minSize]; int actualLength = aesEngine.processBytes(data, 0, length, outBuf, 0); try { actualLength += aesEngine.doFinal(outBuf, actualLength); } catch (Exception e) { if (logger != null) { logger.error("Unable to perform AES cipher.", e); } return new byte[0]; } if (outBuf.length == actualLength) { return outBuf; } else { byte[] result = new byte[actualLength]; System.arraycopy(outBuf, 0, result, 0, result.length); return result; } } /** * CONVENIENCE METHOD ONLY - DO NOT USE UNLESS YOU HAVE TO *

* Use GCM instead, as it's an authenticated cipher (and "regular" AES is not). This prevents tampering with the blocks of encrypted * data. *

* AES encrypt from one stream to another. * * @param aesIV * must be a nonce (unique value) !! * @param logger * may be null, if no log output is necessary * * @return true if successful */ @Deprecated public static boolean encryptStream(BufferedBlockCipher aesEngine, byte[] aesKey, byte[] aesIV, InputStream in, OutputStream out, Logger logger) { byte[] buf = new byte[ivSize]; byte[] outbuf = new byte[512]; CipherParameters aesIVAndKey = new ParametersWithIV(new KeyParameter(aesKey), aesIV); aesEngine.reset(); aesEngine.init(true, aesIVAndKey); try { int bytesRead; int bytesProcessed; while ((bytesRead = in.read(buf)) >= 0) { bytesProcessed = aesEngine.processBytes(buf, 0, bytesRead, outbuf, 0); out.write(outbuf, 0, bytesProcessed); } bytesProcessed = aesEngine.doFinal(outbuf, 0); out.write(outbuf, 0, bytesProcessed); out.flush(); } catch (Exception e) { if (logger != null) { logger.error("Unable to perform AES cipher.", e); } return false; } return true; } /** * AES encrypt from one stream to another. * * @param logger * may be null, if no log output is necessary * @param aesIV * must be a nonce (unique value) !! * * @return true if successful */ public static boolean encryptStream(GCMBlockCipher aesEngine, byte[] aesKey, byte[] aesIV, InputStream in, OutputStream out, Logger logger) { byte[] buf = new byte[ivSize]; byte[] outbuf = new byte[512]; CipherParameters aesIVAndKey = new ParametersWithIV(new KeyParameter(aesKey), aesIV); aesEngine.reset(); aesEngine.init(true, aesIVAndKey); try { int bytesRead; int bytesProcessed; while ((bytesRead = in.read(buf)) >= 0) { bytesProcessed = aesEngine.processBytes(buf, 0, bytesRead, outbuf, 0); out.write(outbuf, 0, bytesProcessed); } bytesProcessed = aesEngine.doFinal(outbuf, 0); out.write(outbuf, 0, bytesProcessed); out.flush(); } catch (Exception e) { if (logger != null) { logger.error("Unable to perform AES cipher.", e); } return false; } return true; } /** * AES decrypt (if the aes IV is included in the data). IV must be a nonce (unique value) !! * * @param logger * may be null, if no log output is necessary * * @return empty byte[] if error */ public static byte[] decryptWithIV(GCMBlockCipher aesEngine, byte[] aesKey, byte[] data, Logger logger) { byte[] aesIV = new byte[ivSize]; System.arraycopy(data, 0, aesIV, 0, ivSize); byte[] in = new byte[data.length - ivSize]; System.arraycopy(data, ivSize, in, 0, in.length); return decrypt(aesEngine, aesKey, aesIV, in, logger); } /** * CONVENIENCE METHOD ONLY - DO NOT USE UNLESS YOU HAVE TO *

* Use GCM instead, as it's an authenticated cipher (and "regular" AES is not). This prevents tampering with the blocks of encrypted * data. *

* AES decrypt (if the aes IV is included in the data). IV must be a nonce (unique value) * * @param logger * may be null, if no log output is necessary * * @return empty byte[] if error */ @Deprecated public static byte[] decryptWithIV(BufferedBlockCipher aesEngine, byte[] aesKey, byte[] data, Logger logger) { byte[] aesIV = new byte[ivSize]; System.arraycopy(data, 0, aesIV, 0, ivSize); byte[] in = new byte[data.length - ivSize]; System.arraycopy(data, ivSize, in, 0, in.length); return decrypt(aesEngine, aesKey, aesIV, in, logger); } /** * AES decrypt (if the aes IV is included in the data. IV must be a nonce (unique value) * * @param logger * may be null, if no log output is necessary * * @return true if successful */ public static boolean decryptStreamWithIV(GCMBlockCipher aesEngine, byte[] aesKey, InputStream in, OutputStream out, Logger logger) { byte[] aesIV = new byte[ivSize]; try { in.read(aesIV, 0, ivSize); } catch (Exception e) { if (logger != null) { logger.error("Unable to perform AES cipher.", e); } return false; } return decryptStream(aesEngine, aesKey, aesIV, in, out, logger); } /** * CONVENIENCE METHOD ONLY - DO NOT USE UNLESS YOU HAVE TO *

* Use GCM instead, as it's an authenticated cipher (and "regular" AES is not). This prevents tampering with the blocks of encrypted * data. *

* AES decrypt (if the aes IV is included in the data). IV must be a nonce (unique value) * * @param logger * may be null, if no log output is necessary * * @return true if successful */ @Deprecated public static boolean decryptStreamWithIV(BufferedBlockCipher aesEngine, byte[] aesKey, InputStream in, OutputStream out, Logger logger) { byte[] aesIV = new byte[ivSize]; try { in.read(aesIV, 0, ivSize); } catch (Exception e) { if (logger != null) { logger.error("Unable to perform AES cipher.", e); } return false; } return decryptStream(aesEngine, aesKey, aesIV, in, out, logger); } /** * AES decrypt (if we already know the aes IV -- and it's NOT included in the data) * * @param aesIV * must be a nonce (unique value) !! * @param logger * may be null, if no log output is necessary * * @return empty byte[] if error */ public static byte[] decrypt(GCMBlockCipher aesEngine, byte[] aesKey, byte[] aesIV, byte[] data, Logger logger) { int length = data.length; CipherParameters aesIVAndKey = new ParametersWithIV(new KeyParameter(aesKey), aesIV); aesEngine.reset(); aesEngine.init(false, aesIVAndKey); int minSize = aesEngine.getOutputSize(length); byte[] outBuf = new byte[minSize]; int actualLength = aesEngine.processBytes(data, 0, length, outBuf, 0); try { actualLength += aesEngine.doFinal(outBuf, actualLength); } catch (Exception e) { if (logger != null) { logger.debug("Unable to perform AES cipher.", e); } return new byte[0]; } if (outBuf.length == actualLength) { return outBuf; } else { byte[] result = new byte[actualLength]; System.arraycopy(outBuf, 0, result, 0, result.length); return result; } } /** * CONVENIENCE METHOD ONLY - DO NOT USE UNLESS YOU HAVE TO *

* Use GCM instead, as it's an authenticated cipher (and "regular" AES is not). This prevents tampering with the blocks of encrypted * data. *

* AES decrypt (if we already know the aes IV -- and it's NOT included in the data) * * @param aesIV * must be a nonce (unique value) !! * @param logger * may be null, if no log output is necessary * * @return empty byte[] if error */ @Deprecated public static byte[] decrypt(BufferedBlockCipher aesEngine, byte[] aesKey, byte[] aesIV, byte[] data, Logger logger) { int length = data.length; CipherParameters aesIVAndKey = new ParametersWithIV(new KeyParameter(aesKey), aesIV); aesEngine.reset(); aesEngine.init(false, aesIVAndKey); int minSize = aesEngine.getOutputSize(length); byte[] outBuf = new byte[minSize]; int actualLength = aesEngine.processBytes(data, 0, length, outBuf, 0); try { actualLength += aesEngine.doFinal(outBuf, actualLength); } catch (Exception e) { if (logger != null) { logger.error("Unable to perform AES cipher.", e); } return new byte[0]; } if (outBuf.length == actualLength) { return outBuf; } else { byte[] result = new byte[actualLength]; System.arraycopy(outBuf, 0, result, 0, result.length); return result; } } /** * AES decrypt from one stream to another. * * @param aesIV * must be a nonce (unique value) !! * @param logger * may be null, if no log output is necessary * * @return true if successful */ public static boolean decryptStream(GCMBlockCipher aesEngine, byte[] aesKey, byte[] aesIV, InputStream in, OutputStream out, Logger logger) { byte[] buf = new byte[ivSize]; byte[] outbuf = new byte[512]; CipherParameters aesIVAndKey = new ParametersWithIV(new KeyParameter(aesKey), aesIV); aesEngine.reset(); aesEngine.init(false, aesIVAndKey); try { int bytesRead; int bytesProcessed; while ((bytesRead = in.read(buf)) >= 0) { bytesProcessed = aesEngine.processBytes(buf, 0, bytesRead, outbuf, 0); out.write(outbuf, 0, bytesProcessed); } bytesProcessed = aesEngine.doFinal(outbuf, 0); out.write(outbuf, 0, bytesProcessed); out.flush(); } catch (Exception e) { if (logger != null) { logger.error("Unable to perform AES cipher.", e); } return false; } return true; } /** * CONVENIENCE METHOD ONLY - DO NOT USE UNLESS YOU HAVE TO *

* Use GCM instead, as it's an authenticated cipher (and "regular" AES is not). This prevents tampering with the blocks of encrypted * data. *

* AES decrypt from one stream to another. * * @param aesIV * must be a nonce (unique value) !! * @param logger * may be null, if no log output is necessary * * @return true if successful */ @Deprecated public static boolean decryptStream(BufferedBlockCipher aesEngine, byte[] aesKey, byte[] aesIV, InputStream in, OutputStream out, Logger logger) { byte[] buf = new byte[ivSize]; byte[] outbuf = new byte[512]; CipherParameters aesIVAndKey = new ParametersWithIV(new KeyParameter(aesKey), aesIV); aesEngine.reset(); aesEngine.init(false, aesIVAndKey); try { int bytesRead; int bytesProcessed; while ((bytesRead = in.read(buf)) >= 0) { bytesProcessed = aesEngine.processBytes(buf, 0, bytesRead, outbuf, 0); out.write(outbuf, 0, bytesProcessed); } bytesProcessed = aesEngine.doFinal(outbuf, 0); out.write(outbuf, 0, bytesProcessed); out.flush(); } catch (Exception e) { if (logger != null) { logger.error("Unable to perform AES cipher.", e); } return false; } return true; } private CryptoAES() { } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy