/// <summary>Encrypt a byte array in blocks with AES algorithm in CBC mode.</summary> /// <remarks>Encrypt a byte array in blocks with AES algorithm in CBC mode.</remarks> /// <param name="plainInput">Plain byte array to encrypt</param> /// <param name="key">256 Bit key to encrypt plainInput</param> /// <returns>Return encrypted byte array</returns> public virtual byte[] encrypt(byte[] plainInput, byte[] key) { int inputLength = plainInput.Length; int percentProgress; int prevPercent = -1; byte[] inputLengthByte = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putInt(inputLength).array(); int restInput = plainInput.Length % nBytes; byte[] exKey = initKeyExpand(key); byte[] cipher = new byte[nBytes]; byte[] cryptOutput = new byte[(inputLength - restInput) + nBytes * 2]; int outputLength = cryptOutput.Length; byte[] initVector = new byte[nBytes]; byte[] nextBlock = new byte[nBytes]; SecureRandom scRandom = new SecureRandom(); // Copy plaintext Array into crypt Array System.Array.Copy(plainInput, 0, cryptOutput, 0, inputLength); // Fill Initialization Vector with Random Bytes scRandom.nextBytes(initVector); // Copy first Input Block to nextBlock System.Array.Copy(cryptOutput, 0, nextBlock, 0, nBytes); // XOR Random initVektor with first Input Block nextBlock = CryptobyHelper.xorByteArrays(nextBlock, initVector); // Copy xored prevBlock into first Input Block System.Array.Copy(nextBlock, 0, cryptOutput, 0, nBytes); // Encrypt last BlockArray initVector = encryptCipher(initVector, exKey); // Add the initVector Array in to last BlockArray and encrypt it System.Array.Copy(initVector, 0, cryptOutput, outputLength - nBytes, nBytes); // Add in the first Byte after CryptText the origin length of plaintext Array System.Array.Copy(inputLengthByte, 0, cryptOutput, outputLength - nBytes * 2, 4); // Encrypt every Block in CBC Mode for (int i = 0; i < outputLength - nBytes; i += nBytes) { // Convert i to percent for ProgressBar // percentProgress = (int)(((float)i / (float)(outputLength - nBytes)) * 100); // // Print ProgressBar // if (percentProgress > prevPercent) // { // CryptobyHelper.printProgressBar(percentProgress); // } // prevPercent = percentProgress; // Copy current block in to Cipher Array System.Array.Copy(nextBlock, 0, cipher, 0, nBytes); // Encrypt Cipher cipher = this.encryptCipher(cipher, exKey); // CBC Mode: XOR next PlainBlock with encrypted Cipher if (i + nBytes < outputLength) { System.Array.Copy(cryptOutput, i + nBytes, nextBlock, 0, nBytes); nextBlock = CryptobyHelper.xorByteArrays(nextBlock, cipher); } // Copy Cipher back in decryptOutput Array System.Array.Copy(cipher, 0, cryptOutput, i, nBytes); } // CryptobyHelper.printProgressBar(100); return(cryptOutput); }
/// <summary>Encrypt plainInput with publicKey in blocks.</summary> /// <remarks> /// Encrypt plainInput with publicKey in blocks. The first encrypted block will /// be xored with a Initial Vektor and every next encrypted block will be xored /// with the previous block and written to output array. Encrypted Initial /// Vector stored in last two bytes of output byte array. /// </remarks> /// <param name="plainInput">Byte Array to encrypt in RSA Mode</param> /// <param name="publicKey">RSA Public Key as Byte Array</param> /// <returns>RSA Encrypted plainInput as Byte Array</returns> public virtual byte[] encrypt(byte[] plainInput, byte[] publicKey) { BigInteger n = new BigInteger(publicKey); int keySize = publicKey.Length; int dataBlockSize = keySize + 2 * (keySize / 128); int plainBlockSize = keySize - 2; int wholeLen = plainInput.Length; int cryptBlocksLen = (wholeLen / plainBlockSize) * dataBlockSize; int dataBlocksLen = cryptBlocksLen + 3 * dataBlockSize; int plainBlocksLen = (wholeLen / plainBlockSize) * plainBlockSize; byte[] cryptOutput = new byte[dataBlocksLen]; if (wholeLen > keySize) { int percentProgress; int prevPercent = -1; int plainPlusOneBlockSize = plainBlockSize + 1; int rest = wholeLen - plainBlocksLen; int halfOfVektor; byte[] dataBlock = new byte[dataBlockSize]; byte[] cryptBlock; byte[] plainBlock = new byte[plainBlockSize]; byte[] plusOnePlainBlock = new byte[plainPlusOneBlockSize]; byte[] initVektorBlock; byte[] firstVektorBlock; byte[] secVektorBlock; byte[] cryptBlockSize; byte[] one = BigInteger.ONE.toByteArray(); do { SecureRandom rnd = new SecureRandom(); halfOfVektor = dataBlockSize / 2; do { firstVektorBlock = new BigInteger(halfOfVektor * 8 - 1, rnd).toByteArray(); secVektorBlock = new BigInteger(halfOfVektor * 8 - 1, rnd).toByteArray(); }while (firstVektorBlock.Length != halfOfVektor || secVektorBlock.Length != halfOfVektor); initVektorBlock = new byte[dataBlockSize]; System.Array.Copy(firstVektorBlock, 0, initVektorBlock, 0, halfOfVektor); System.Array.Copy(secVektorBlock, 0, initVektorBlock, halfOfVektor, halfOfVektor); firstVektorBlock = encryptBlock(firstVektorBlock, n); secVektorBlock = encryptBlock(secVektorBlock, n); }while (firstVektorBlock.Length != keySize || secVektorBlock.Length != keySize); byte[] prevBlock = new byte[dataBlockSize]; System.Array.Copy(initVektorBlock, 0, prevBlock, 0, dataBlockSize); byte[] nextBlock = new byte[dataBlockSize]; int j = 0; for (int i = 0; i < plainBlocksLen; i += plainBlockSize) { // Convert i to percent for ProgressBar percentProgress = (int)(((float)i / (float)plainBlocksLen) * 100); // Print ProgressBar // if (percentProgress > prevPercent) // { // CryptobyHelper.printProgressBar(percentProgress); // } prevPercent = percentProgress; // Copy Part of PlainInput in to Block System.Array.Copy(plainInput, i, plainBlock, 0, plainBlockSize); // Add a One Byte into first Byte of Plain Array System.Array.Copy(one, 0, plusOnePlainBlock, 0, one.Length); System.Array.Copy(plainBlock, 0, plusOnePlainBlock, 1, plainBlockSize); // Encrypt Block cryptBlock = encryptBlock(plusOnePlainBlock, n); // Copy Crypt Block in to extended DataBlock System.Array.Copy(cryptBlock, 0, dataBlock, 0, cryptBlock.Length); // Copy in last Byte of dataBlock the Size of cryptBlock cryptBlockSize = BigInteger.valueOf(cryptBlock.Length - keySize).toByteArray(); System.Array.Copy(cryptBlockSize, 0, dataBlock, dataBlock.Length - 1, cryptBlockSize .Length); System.Array.Copy(dataBlock, 0, nextBlock, 0, dataBlockSize); // XOR dataBlock with prevBlock dataBlock = CryptobyHelper.xorByteArrays(dataBlock, prevBlock); System.Array.Copy(nextBlock, 0, prevBlock, 0, dataBlockSize); // Copy xored dataBlock to Output Array System.Array.Copy(dataBlock, 0, cryptOutput, j, dataBlockSize); j += dataBlockSize; } if (rest != 0) { // crypt rest of PlainInput plainBlock = new byte[rest]; plusOnePlainBlock = new byte[rest + 1]; dataBlock = new byte[dataBlockSize]; System.Array.Copy(plainInput, plainBlocksLen, plainBlock, 0, plainBlock.Length); // Add a One Byte in to first Byte of Plain Array System.Array.Copy(one, 0, plusOnePlainBlock, 0, one.Length); System.Array.Copy(plainBlock, 0, plusOnePlainBlock, 1, plainBlock.Length); // Encrypt rest of PlainInput cryptBlock = encryptBlock(plusOnePlainBlock, n); System.Array.Copy(cryptBlock, 0, dataBlock, 0, cryptBlock.Length); // Copy in last Byte of dataBlock the Size of cryptBlock cryptBlockSize = BigInteger.valueOf(cryptBlock.Length - keySize).toByteArray(); System.Array.Copy(cryptBlockSize, 0, dataBlock, dataBlock.Length - 1, 1); // XOR dataBlock with prevBlock dataBlock = CryptobyHelper.xorByteArrays(dataBlock, prevBlock); System.Array.Copy(dataBlock, 0, cryptOutput, dataBlocksLen - 3 * dataBlockSize, dataBlockSize ); } else { dataBlock = new byte[dataBlockSize]; System.Array.Copy(dataBlock, 0, cryptOutput, dataBlocksLen - 3 * dataBlockSize, dataBlockSize ); } // Put crypted initVektor into last 2 Bytes of cryptOutput Array System.Array.Copy(firstVektorBlock, 0, cryptOutput, dataBlocksLen - 2 * dataBlockSize , firstVektorBlock.Length); System.Array.Copy(secVektorBlock, 0, cryptOutput, dataBlocksLen - 1 * dataBlockSize , secVektorBlock.Length); } else { cryptOutput = encryptBlock(plainInput, n); } //CryptobyHelper.printProgressBar(100); return(cryptOutput); }
/// <summary>Decrypt a byte array in blocks with AES algorithm in CBC mode.</summary> /// <remarks>Decrypt a byte array in blocks with AES algorithm in CBC mode.</remarks> /// <param name="cryptInput">Encrypted byte array to decrypt</param> /// <param name="key">256 Bit key to decrypt cryptInput</param> /// <returns>Return decrypted byte array</returns> public virtual byte[] decrypt(byte[] cryptInput, byte[] key) { int percentProgress; int prevPercent = -1; byte[] exKey = initKeyExpand(key); int outputLength = cryptInput.Length; byte[] decryptOutput = new byte[outputLength]; System.Array.Copy(cryptInput, 0, decryptOutput, 0, outputLength); byte[] cipher = new byte[nBytes]; byte[] inputLengthByte = new byte[nBytes]; byte[] plainOutput; byte[] initVector = new byte[nBytes]; byte[] prevBlock = new byte[nBytes]; // Add the initVector Array in to last BlockArray and encrypt it System.Array.Copy(decryptOutput, outputLength - nBytes, initVector, 0, nBytes); // Decrypt last BlockArray initVector = this.decryptCipher(initVector, exKey); // Copy initVector to prevBlock Array System.Array.Copy(initVector, 0, prevBlock, 0, nBytes); for (int i = 0; i < outputLength - nBytes; i += nBytes) { // // Convert i to percent for ProgressBar // percentProgress = (int)(((float)i / (float)(outputLength - nBytes)) * 100); // // Print ProgressBar // if (percentProgress > prevPercent) // { // CryptobyHelper.printProgressBar(percentProgress); // } // prevPercent = percentProgress; // Copy current block in to Cipher Array System.Array.Copy(decryptOutput, i, cipher, 0, nBytes); // Decrypt Cipher cipher = this.decryptCipher(cipher, exKey); // CBC Mode: XOR next PlainBlock with encrypted Cipher if (i + nBytes < outputLength) { cipher = CryptobyHelper.xorByteArrays(prevBlock, cipher); System.Array.Copy(decryptOutput, i, prevBlock, 0, nBytes); } // Copy Cipher back in current decryptOutput Array System.Array.Copy(cipher, 0, decryptOutput, i, nBytes); } // Read last Index of encryptet Output // and use the Integer Content for lenght of plainOutput System.Array.Copy(decryptOutput, outputLength - nBytes * 2, inputLengthByte, 0, 4); int lengthOriginArray = ByteBuffer.wrap(inputLengthByte).order(ByteOrder.BIG_ENDIAN ).getInt(); try { plainOutput = new byte[lengthOriginArray]; System.Array.Copy(decryptOutput, 0, plainOutput, 0, lengthOriginArray); } catch (Exception) { plainOutput = cryptInput; } // CryptobyHelper.printProgressBar(100); return(plainOutput); }
/// <summary>Decrypt cryptInput with privateKey in blocks.</summary> /// <remarks> /// Decrypt cryptInput with privateKey in blocks. Initial Vector in last two /// bytes will be decrypt and used to xor the first decrypted block. Every next /// block will be xored with the previous block. After every XOR the block /// will be decrypted and written to output byte array. /// </remarks> /// <param name="cryptInput">RSA Encrypted Input as Byte Array</param> /// <param name="privateKey">RSA Private Key as Byte Array</param> /// <returns>RSA decrypted cryptInput as Byte Array</returns> public virtual byte[] decrypt(byte[] cryptInput, byte[] privateKey) { byte[] dByteArray = getDfromKey(privateKey); byte[] nByteArray = getNfromKey(privateKey); BigInteger d = new BigInteger(dByteArray); BigInteger n = new BigInteger(nByteArray); int keySize = nByteArray.Length; int dataBlockSize = keySize + 2 * (keySize / 128); int plainBlockSize = keySize - 2; int wholeLen = cryptInput.Length; int dataBlocksLen = wholeLen - 3 * dataBlockSize; int plainBlocksLen; int halfOfVektor = dataBlockSize / 2; int percentProgress; byte[] plainOutput; byte[] allPlainBlocks; byte[] cryptBlock; byte[] plainBlock = new byte[plainBlockSize]; byte[] plusOnePlainBlock; byte[] dataBlock = new byte[dataBlockSize]; byte[] prevBlock = new byte[dataBlockSize]; byte[] initVektorBlock = new byte[dataBlockSize]; byte[] firstVektorBlock = new byte[keySize]; byte[] secVektorBlock = new byte[keySize]; byte[] cryptBlockSize; if (wholeLen > keySize) { plainBlocksLen = (dataBlocksLen / dataBlockSize) * plainBlockSize; allPlainBlocks = new byte[plainBlocksLen]; // Get initVektor from last 2 Bytes of CryptInput System.Array.Copy(cryptInput, wholeLen - 2 * dataBlockSize, firstVektorBlock, 0, keySize); System.Array.Copy(cryptInput, wholeLen - 1 * dataBlockSize, secVektorBlock, 0, keySize ); // Decrypt Vektors and merge together firstVektorBlock = decryptBlock(firstVektorBlock, n, d); secVektorBlock = decryptBlock(secVektorBlock, n, d); System.Array.Copy(firstVektorBlock, 0, initVektorBlock, 0, halfOfVektor); System.Array.Copy(secVektorBlock, 0, initVektorBlock, halfOfVektor, halfOfVektor); System.Array.Copy(initVektorBlock, 0, prevBlock, 0, dataBlockSize); int j = 0; for (int i = 0; i < dataBlocksLen; i += dataBlockSize) { // Convert i to percent for ProgressBar percentProgress = (int)(((float)i / (float)dataBlocksLen) * 100); // Print ProgressBar //CryptobyHelper.printProgressBar(percentProgress); System.Array.Copy(cryptInput, i, dataBlock, 0, dataBlockSize); // XOR with prevBlock dataBlock = CryptobyHelper.xorByteArrays(prevBlock, dataBlock); System.Array.Copy(dataBlock, 0, prevBlock, 0, dataBlockSize); // Get Size of cryptBlock cryptBlockSize = new byte[1]; System.Array.Copy(dataBlock, dataBlock.Length - 1, cryptBlockSize, 0, 1); cryptBlock = new byte[keySize + new BigInteger(cryptBlockSize).intValue()]; System.Array.Copy(dataBlock, 0, cryptBlock, 0, cryptBlock.Length); // Decrypt cryptBlock plusOnePlainBlock = decryptBlock(cryptBlock, n, d); // Remove one from first Byte of Array System.Array.Copy(plusOnePlainBlock, 1, plainBlock, 0, plainBlockSize); System.Array.Copy(plainBlock, 0, allPlainBlocks, j, plainBlockSize); j += plainBlockSize; } dataBlock = new byte[dataBlockSize]; System.Array.Copy(cryptInput, dataBlocksLen, dataBlock, 0, dataBlockSize); if (new BigInteger(dataBlock).compareTo(BigInteger.ZERO) != 0) { dataBlock = CryptobyHelper.xorByteArrays(prevBlock, dataBlock); cryptBlockSize = new byte[1]; System.Array.Copy(dataBlock, dataBlock.Length - 1, cryptBlockSize, 0, 1); cryptBlock = new byte[keySize + new BigInteger(cryptBlockSize).intValue()]; System.Array.Copy(dataBlock, 0, cryptBlock, 0, cryptBlock.Length); plusOnePlainBlock = decryptBlock(cryptBlock, n, d); plainBlock = new byte[plusOnePlainBlock.Length - 1]; // Remove one from first Byte of Array System.Array.Copy(plusOnePlainBlock, 1, plainBlock, 0, plainBlock.Length); plainOutput = new byte[plainBlocksLen + plainBlock.Length]; System.Array.Copy(allPlainBlocks, 0, plainOutput, 0, plainBlocksLen); System.Array.Copy(plainBlock, 0, plainOutput, plainBlocksLen, plainBlock.Length); } else { plainOutput = new byte[plainBlocksLen]; System.Array.Copy(allPlainBlocks, 0, plainOutput, 0, plainBlocksLen); } } else { plainOutput = decryptBlock(cryptInput, n, d); } // Print ProgressBar //CryptobyHelper.printProgressBar(100); return(plainOutput); }