List of usage examples for org.bouncycastle.crypto.modes GCMBlockCipher reset
public void reset()
From source file:dorkbox.network.connection.KryoExtra.java
License:Apache License
public synchronized void writeCrypto(final Connection_ connection, final ByteBuf buffer, final Object message) throws IOException { // required by RMI and some serializers to determine which connection wrote (or has info about) this object this.rmiSupport = connection.rmiSupport(); ByteBuf objectOutputBuffer = this.tempBuffer; objectOutputBuffer.clear(); // always have to reset everything // write the object to a TEMP buffer! this will be compressed writer.setBuffer(objectOutputBuffer); writeClassAndObject(writer, message); // save off how much data the object took int length = objectOutputBuffer.writerIndex(); // NOTE: compression and encryption MUST work with byte[] because they use JNI! // Realistically, it is impossible to get the backing arrays out of a Heap Buffer once they are resized and begin to use // sliced. It's lame that there is a "double copy" of bytes here, but I don't know how to avoid it... // see: https://stackoverflow.com/questions/19296386/netty-java-getting-data-from-bytebuf byte[] inputArray; int inputOffset; // Even if a ByteBuf has a backing array (i.e. buf.hasArray() returns true), the using it isn't always possible because // the buffer might be a slice of other buffer or a pooled buffer: //noinspection Duplicates if (objectOutputBuffer.hasArray() && objectOutputBuffer.array()[0] == objectOutputBuffer.getByte(0) && objectOutputBuffer.array().length == objectOutputBuffer.capacity()) { // we can use it... inputArray = objectOutputBuffer.array(); inputArrayLength = -1; // this is so we don't REUSE this array accidentally! inputOffset = objectOutputBuffer.arrayOffset(); } else {//from w w w . jav a2 s . com // we can NOT use it. if (length > inputArrayLength) { inputArrayLength = length; inputArray = new byte[length]; this.inputArray = inputArray; } else { inputArray = this.inputArray; } objectOutputBuffer.getBytes(objectOutputBuffer.readerIndex(), inputArray, 0, length); inputOffset = 0; } ////////// compressing data // we ALWAYS compress our data stream -- because of how AES-GCM pads data out, the small input (that would result in a larger // output), will be negated by the increase in size by the encryption byte[] compressOutput = this.compressOutput; int maxLengthLengthOffset = 4; // length is never negative, so 4 is OK (5 means it's negative) int maxCompressedLength = compressor.maxCompressedLength(length); // add 4 so there is room to write the compressed size to the buffer int maxCompressedLengthWithOffset = maxCompressedLength + maxLengthLengthOffset; // lazy initialize the compression output buffer if (maxCompressedLengthWithOffset > compressOutputLength) { compressOutputLength = maxCompressedLengthWithOffset; compressOutput = new byte[maxCompressedLengthWithOffset]; this.compressOutput = compressOutput; } // LZ4 compress. output offset max 4 bytes to leave room for length of tempOutput data int compressedLength = compressor.compress(inputArray, inputOffset, length, compressOutput, maxLengthLengthOffset, maxCompressedLength); // bytes can now be written to, because our compressed data is stored in a temp array. final int lengthLength = OptimizeUtilsByteArray.intLength(length, true); // correct input. compression output is now encryption input inputArray = compressOutput; inputOffset = maxLengthLengthOffset - lengthLength; // now write the ORIGINAL (uncompressed) length to the front of the byte array. This is so we can use the FAST decompress version OptimizeUtilsByteArray.writeInt(inputArray, length, true, inputOffset); // correct length for encryption length = compressedLength + lengthLength; // +1 to +4 for the uncompressed size bytes /////// encrypting data. final long nextGcmSequence = connection.getNextGcmSequence(); // this is a threadlocal, so that we don't clobber other threads that are performing crypto on the same connection at the same time final ParametersWithIV cryptoParameters = connection.getCryptoParameters(); BigEndian.Long_.toBytes(nextGcmSequence, cryptoParameters.getIV(), 4); // put our counter into the IV final GCMBlockCipher aes = this.aesEngine; aes.reset(); aes.init(true, cryptoParameters); byte[] cryptoOutput; // lazy initialize the crypto output buffer int cryptoSize = length + 16; // from: aes.getOutputSize(length); // 'output' is the temp byte array if (cryptoSize > cryptoOutputLength) { cryptoOutputLength = cryptoSize; cryptoOutput = new byte[cryptoSize]; this.cryptoOutput = cryptoOutput; } else { cryptoOutput = this.cryptoOutput; } int encryptedLength = aes.processBytes(inputArray, inputOffset, length, cryptoOutput, 0); try { // authentication tag for GCM encryptedLength += aes.doFinal(cryptoOutput, encryptedLength); } catch (Exception e) { throw new IOException("Unable to AES encrypt the data", e); } // write out our GCM counter OptimizeUtilsByteBuf.writeLong(buffer, nextGcmSequence, true); // have to copy over the orig data, because we used the temp buffer buffer.writeBytes(cryptoOutput, 0, encryptedLength); }
From source file:dorkbox.network.connection.KryoExtra.java
License:Apache License
public Object readCrypto(final Connection_ connection, final ByteBuf buffer, int length) throws IOException { // required by RMI and some serializers to determine which connection wrote (or has info about) this object this.rmiSupport = connection.rmiSupport(); //////////////// // Note: we CANNOT write BACK to the buffer as "temp" storage, since there could be additional data on it! //////////////// ByteBuf inputBuf = buffer;/* ww w . ja v a 2 s . c o m*/ final long gcmIVCounter = OptimizeUtilsByteBuf.readLong(buffer, true); int lengthLength = OptimizeUtilsByteArray.longLength(gcmIVCounter, true); // have to adjust for the gcmIVCounter length = length - lengthLength; /////////// decrypting data // NOTE: compression and encryption MUST work with byte[] because they use JNI! // Realistically, it is impossible to get the backing arrays out of a Heap Buffer once they are resized and begin to use // sliced. It's lame that there is a "double copy" of bytes here, but I don't know how to avoid it... // see: https://stackoverflow.com/questions/19296386/netty-java-getting-data-from-bytebuf byte[] inputArray; int inputOffset; // Even if a ByteBuf has a backing array (i.e. buf.hasArray() returns true), the using it isn't always possible because // the buffer might be a slice of other buffer or a pooled buffer: //noinspection Duplicates if (inputBuf.hasArray() && inputBuf.array()[0] == inputBuf.getByte(0) && inputBuf.array().length == inputBuf.capacity()) { // we can use it... inputArray = inputBuf.array(); inputArrayLength = -1; // this is so we don't REUSE this array accidentally! inputOffset = inputBuf.arrayOffset() + lengthLength; } else { // we can NOT use it. if (length > inputArrayLength) { inputArrayLength = length; inputArray = new byte[length]; this.inputArray = inputArray; } else { inputArray = this.inputArray; } inputBuf.getBytes(inputBuf.readerIndex(), inputArray, 0, length); inputOffset = 0; } // have to make sure to set the position of the buffer, since our conversion to array DOES NOT set the new reader index. buffer.readerIndex(buffer.readerIndex() + length); // this is a threadlocal, so that we don't clobber other threads that are performing crypto on the same connection at the same time final ParametersWithIV cryptoParameters = connection.getCryptoParameters(); BigEndian.Long_.toBytes(gcmIVCounter, cryptoParameters.getIV(), 4); // put our counter into the IV final GCMBlockCipher aes = this.aesEngine; aes.reset(); aes.init(false, cryptoParameters); int cryptoSize = length - 16; // from: aes.getOutputSize(length); // lazy initialize the decrypt output buffer byte[] decryptOutputArray; if (cryptoSize > decryptOutputLength) { decryptOutputLength = cryptoSize; decryptOutputArray = new byte[cryptoSize]; this.decryptOutput = decryptOutputArray; decryptBuf = Unpooled.wrappedBuffer(decryptOutputArray); } else { decryptOutputArray = this.decryptOutput; } int decryptedLength = aes.processBytes(inputArray, inputOffset, length, decryptOutputArray, 0); try { // authentication tag for GCM decryptedLength += aes.doFinal(decryptOutputArray, decryptedLength); } catch (Exception e) { throw new IOException("Unable to AES decrypt the data", e); } ///////// decompress data -- as it's ALWAYS compressed // get the decompressed length (at the beginning of the array) inputArray = decryptOutputArray; final int uncompressedLength = OptimizeUtilsByteArray.readInt(inputArray, true); inputOffset = OptimizeUtilsByteArray.intLength(uncompressedLength, true); // because 1-4 bytes for the decompressed size byte[] decompressOutputArray = this.decompressOutput; if (uncompressedLength > decompressOutputLength) { decompressOutputLength = uncompressedLength; decompressOutputArray = new byte[uncompressedLength]; this.decompressOutput = decompressOutputArray; decompressBuf = Unpooled.wrappedBuffer(decompressOutputArray); // so we can read via kryo } inputBuf = decompressBuf; // LZ4 decompress, requires the size of the ORIGINAL length (because we use the FAST decompressor decompressor.decompress(inputArray, inputOffset, decompressOutputArray, 0, uncompressedLength); inputBuf.setIndex(0, uncompressedLength); // read the object from the buffer. reader.setBuffer(inputBuf); return readClassAndObject(reader); // this properly sets the readerIndex, but only if it's the correct buffer }
From source file:dorkbox.util.crypto.CryptoAES.java
License:Apache License
/** * AES encrypts data with a specified key. * * @param logger//w w w .jav a 2s . c om * 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; } }
From source file:dorkbox.util.crypto.CryptoAES.java
License:Apache License
/** * AES encrypt from one stream to another. * * @param logger/*from w w w . java 2 s. co m*/ * 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; }
From source file:dorkbox.util.crypto.CryptoAES.java
License:Apache License
/** * AES decrypt (if we already know the aes IV -- and it's NOT included in the data) * * @param aesIV/*ww w .j a v a 2 s. co m*/ * 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; } }
From source file:dorkbox.util.crypto.CryptoAES.java
License:Apache License
/** * AES decrypt from one stream to another. * * @param aesIV/*ww w.ja v a 2 s . co m*/ * 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; }
From source file:dorkbox.util.crypto.PerformanceTest.java
License:Apache License
PerformanceTest(boolean isWarmup) { final byte[] bytes = new byte[64 * 1024]; byte[] encrypted = null; final byte[] aesKey = new byte[32]; final byte[] aesIV = new byte[12]; final Random random = new SecureRandom(entropySeed.getBytes()); random.nextBytes(bytes);// w w w . j a v a2s . c o m random.nextBytes(aesKey); random.nextBytes(aesIV); int length = bytes.length; if (!isWarmup) { System.out.println("Benchmarking AES-256 GCM encryption"); } long javaEncryptInputBytes = 0; long javaEncryptStartTime = System.currentTimeMillis(); // convert to bouncycastle GCMBlockCipher aesEngine = new GCMBlockCipher(new AESFastEngine()); CipherParameters aesIVAndKey = new ParametersWithIV(new KeyParameter(aesKey), aesIV); long encryptInitTime = 0L; long encryptUpdate1Time = 0L; long encryptDoFinalTime = 0L; while (System.currentTimeMillis() - javaEncryptStartTime < 10000) { random.nextBytes(aesIV); long n1 = System.nanoTime(); aesEngine.reset(); aesEngine.init(true, aesIVAndKey); if (encrypted == null) { int minSize = aesEngine.getOutputSize(length); encrypted = new byte[minSize]; } long n2 = System.nanoTime(); int actualLength = aesEngine.processBytes(bytes, 0, length, encrypted, 0); long n3 = System.nanoTime(); try { actualLength += aesEngine.doFinal(encrypted, actualLength); } catch (Exception e) { logger.error("Unable to perform AES cipher.", e); } if (encrypted.length != actualLength) { byte[] result = new byte[actualLength]; System.arraycopy(encrypted, 0, result, 0, result.length); encrypted = result; } long n4 = System.nanoTime(); javaEncryptInputBytes += actualLength; encryptInitTime = n2 - n1; encryptUpdate1Time = n3 - n2; encryptDoFinalTime = n4 - n3; } long javaEncryptEndTime = System.currentTimeMillis(); if (!isWarmup) { System.out.println("Time init (ns): " + encryptInitTime); System.out.println("Time update (ns): " + encryptUpdate1Time); System.out.println("Time do final (ns): " + encryptDoFinalTime); System.out.println("Java calculated at " + (javaEncryptInputBytes / 1024 / 1024 / ((javaEncryptEndTime - javaEncryptStartTime) / 1000)) + " MB/s"); System.out.println("Benchmarking AES-256 GCM decryption"); } long javaDecryptInputBytes = 0; long javaDecryptStartTime = System.currentTimeMillis(); length = encrypted.length; long decryptInitTime = 0L; long decryptUpdate1Time = 0L; long decryptDoFinalTime = 0L; while (System.currentTimeMillis() - javaDecryptStartTime < 10000) { long n1 = System.nanoTime(); aesEngine.reset(); aesEngine.init(false, aesIVAndKey); long n2 = System.nanoTime(); int actualLength = aesEngine.processBytes(encrypted, 0, length, bytes, 0); long n3 = System.nanoTime(); try { actualLength += aesEngine.doFinal(bytes, actualLength); } catch (Exception e) { logger.debug("Unable to perform AES cipher.", e); } long n4 = System.nanoTime(); javaDecryptInputBytes += actualLength; decryptInitTime += n2 - n1; decryptUpdate1Time += n3 - n2; decryptDoFinalTime += n4 - n3; } long javaDecryptEndTime = System.currentTimeMillis(); if (!isWarmup) { System.out.println("Time init (ns): " + decryptInitTime); System.out.println("Time update 1 (ns): " + decryptUpdate1Time); System.out.println("Time do final (ns): " + decryptDoFinalTime); System.out.println("Total bytes processed: " + javaDecryptInputBytes); System.out.println("Java calculated at " + (javaDecryptInputBytes / 1024 / 1024 / ((javaDecryptEndTime - javaDecryptStartTime) / 1000)) + " MB/s"); } }