Loading…

Kryptel/Java

Example of File Encryption

Encryption of Arbitrary Size Data

This function encrypts or decrypts the specified file with the supplied password. If the file name has the .enc extension, then the file gets decrypted, and the result is stored to a file with the same name with removed .enc extension. Otherwise the file gets encrypted and stored to a file with added .enc extension.

import static com.kryptel.Guids.CID_CIPHER_AES;
import static com.kryptel.Guids.CID_HASH_SHA256;
import static com.kryptel.Guids.IID_IBlockCipherParams;
import static com.kryptel.Guids.IID_ICipher;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import com.kryptel.ApiHelpers;
import com.kryptel.IDataSink;
import com.kryptel.IKryptelComponent;
import com.kryptel.KeyRecord;
import com.kryptel.Loader;
import com.kryptel.cipher.IBlockCipherParams;
import com.kryptel.cipher.ICipher;

The ICipher interface requires a datasink interface to store the resulting data. Our class DataSink accepts an instance of FileOutputStream class to write the output data to.

class DataSink implements IDataSink {

  private FileOutputStream stream;

  public void Init(Object arg) throws Exception {
    stream = (FileOutputStream)arg;
  }

  public void PutData(byte[] buf, int start, int size) throws Exception {
    stream.write(buf, start, size);
  }

  public void Done() throws Exception { }
}

Our main encryption function FileEncryption accepts a file name and a password, and either encrypts the specified file or decrypts it depending on the presence of the .enc extension.

public static void FileEncryption(String fileName, String password) throws Exception {
  IKryptelComponent compCipher = (IKryptelComponent)Loader.CreateComponent(CID_CIPHER_AES);

  // Set cipher parameters
  IBlockCipherParams cipherParams =
        (IBlockCipherParams)compCipher.GetInterface(IID_IBlockCipherParams);
  cipherParams.SetKeySize(32);  // Set key size to 256 bits
  cipherParams.SetChainingMode(IBlockCipherParams.MODE_CBC);  // Set CBC chaining mode
  // We don't set the init vector, so all zeros init vector will be used

  // Convert the password and set encryption key
  KeyRecord kr = ApiHelpers.PasswordToKeyRecord(password, CID_HASH_SHA256);
  cipherParams.SetKey(kr.keyData, 0, kr.keyData.length);

  ICipher cipher = (ICipher)compCipher.GetInterface(IID_ICipher);

  boolean bEncrypt = !fileName.endsWith(".enc");
  String outputFileName = bEncrypt
                          ? fileName + ".enc"
                          : fileName.substring(0, fileName.length() - 4);

  File f = new File(fileName);
  assert (f.isFile());
  long fsize = f.length();

  byte[] ioBuffer = new byte [64 * 1024];
  int len;

  try (FileInputStream fin = new FileInputStream(fileName);
       FileOutputStream fout = new FileOutputStream(outputFileName)) {
    cipher.Init(new DataSink(), fout);

    while (fsize > 0) {
      len = (int)Math.min(fsize, ioBuffer.length);
      fin.read(ioBuffer, 0, len);
      if (bEncrypt)
        cipher.Encrypt(ioBuffer, 0, len);
      else
        cipher.Decrypt(ioBuffer, 0, len);
      fsize -= len;
    }

    cipher.Done();
    compCipher.DiscardComponent();
  }
}

Cipher interfaces used: ICipher, IBlockCipherParams.

More about components: Components, Loader class, IKryptelComponent interface.

See Also: IDataSink interface, ApiHelpers class, KeyRecord structure.