File Encryption Examples
This page contains example code snippets for typical encryption and backup tasks using File Agent and Backup Agent interfaces.
Contents
- Introduction to the Library
- Basic support package (com.kryptel.bslx)
- Kryptel API Commons package (com.kryptel)
- Cipher package (com.kryptel.cipher)
- Compressor package (com.kryptel.compressor)
- Exceptions package (com.kryptel.exceptions)
- Hash function package (com.kryptel.hash_function)
- MAC function package (com.kryptel.mac)
- Key-related functions (com.kryptel.key)
- Silver Key engine (com.kryptel.silver_key)
- Kryptel encrypted storage (com.kryptel.storage)
- Handlers and Agents
- Names and Unique Names
- Kryptel class
- FileStorageStatistics structure
- StorageStatistics structure
- IEncryptedStorage interface
- IEncryptedStorageInfo interface
- IEncryptedObject interface
- IEncryptedStream interface
- IEncryptedFileStorage interface
- IEncryptedFileStorageInfo interface
- IFileSystemAttributes interface
- IEncryptedDirectory interface
- IEncryptedFile interface
- Example: Password storage
- File encryption examples
Preface
All the examples use this extremely simplified IKeyCallback implementation:
class KeyCallback implements IKeyCallback { private static final String PREDEFINED_PASSWORD = "qwerty"; public KeyRecord Callback(Object arg, String prompt, int allowed, UUID expected) { KeyRecord kr = new KeyRecord(); kr.keyMaterial = KeyIdent.IDENT_PASSWORD; kr.password = PREDEFINED_PASSWORD; return kr; } }
In order to reduce unrelated code as much as possible, these examples use a hard-wired password. A real-life program must never use hard-wired passwords as that makes encryption pretty useless.
To simplify the code further we don't use any callbacks except the required key callback. There are several examples in other parts on creating and using optional callbacks: progress, replace, and others.
Encrypting a File
This example creates a container contPath and stores there a file filePath.
IKryptelComponent krComp = Loader.CreateComponent(CID_FILE_AGENT); IEncryptedFileStorage stor = (IEncryptedFileStorage)krComp.GetInterface(IID_IEncryptedFileStorage); stor.Create(contPath, Loader.CreateComponent(CID_CIPHER_AES), Loader.CreateComponent(CID_COMPRESSOR_ZIP), Loader.CreateComponent(CID_HASH_SHA256), CID_STORAGE_7, null, new KeyCallback()); IEncryptedDirectory root = stor.GetRootDir(TARGET_DEFAULT); root.StartEncryptionBatch(); root.AddToEncryptionBatch(filePath); root.EncryptBatch(null, null, null, null); stor.Close();
The result is a simple single-file container without any internal directory structure. If we right-click it and select Decrypt, Kryptel will decrypt that file into the current directory.
Using Backup Agent
What happens if we just replace CID_FILE_AGENT with CID_BACKUP_AGENT? Instead of simple file encryption we will create its backup, i.e. the agent will also store file's targeted path (read more about targets). Decryption operation will restore the file to its original location (unless we don't specify an alternate one).
Target recognition occured because we encrypted the file to the special directory designated by TARGET_DEFAULT pseudo-target. If that were a real target like Drive C or My Documents, the file would be encrypted there, but TARGET_DEFAULT corresponds to no real target and just instructs the backup agent to recognize the target from the file's original location.
For a more detailed discussion see Kryptel Agents, the Notes part.
Decrypting Container Contents
This example opens a container contPath and decrypts its contents to a directory targetDir.
ContainerHandlers ch = GetContainerHandlers(contPath); if (ch == null) throw new Exception("Not a valid container"); if (ch.agent == null) throw new Exception("Not a file container"); IKryptelComponent krComp = Loader.CreateComponent(ch.agent); if (krComp == null) throw new Exception("Unknown agent or not a file container"); IEncryptedFileStorage stor = (IEncryptedFileStorage)krComp.GetInterface(IID_IEncryptedFileStorage); if (stor == null) throw new Exception("Not a file container"); stor.Open(contPath, IEncryptedStorage.CONTAINER_ACCESS_MODE.CONT_READ_ONLY, null, new KeyCallback()); IEncryptedDirectory root = stor.GetRootDir(TARGET_DEFAULT); root.Decrypt(targetDir, null, null, null); stor.Close();
We don't make any assumption about the type of the agent and instead get handlers' IDs with GetContainerHandlers function, so this code chunk will correctly open containers associated with any file or backup agent.
Note that for File Agent you must specify a valid non-empty targetDir because standard file container does not keep the base path to which its files and directory trees should be decrypted.
In case of Backup Agent, targetDir may be empty. If it is empty, then all the items will be restored to their original locations.
Partial Decryption
Decrypting the whole container contents is not necessary if we need just a few items.
IEncryptedDirectory root = stor.GetRootDir(TARGET_DEFAULT); root.StartDecryptionBatch(targetDir); root.AddToDecryptionBatch("file.ext"); root.AddToDecryptionBatch("Subdir/file2.ext"); root.AddToDecryptionBatch("Subdir/AnotherSubdir"); root.DecryptBatch(null, null, null); stor.Close();
Note however that this code will not work with a backup agent. TARGET_DEFAULT does not correspond to any real target and allows only a limited set of operations, specifically, decrypting the whole contents with the Decrypt function as in the previous example. In order to restore a selected set of items specify a real target:
IEncryptedDirectory root = stor.GetRootDir(TARGET_DOCUMENTS); root.StartDecryptionBatch(""); root.AddToDecryptionBatch("report1.xls"); root.AddToDecryptionBatch("2017/applist.doc"); root.DecryptBatch(null, null, null); stor.Close();
The code above will restore a file and a subfolder with another file to their original locations (My Documents). Note that this code is valid for backup agent only. File agent allows only TARGET_DEFAULT and requires a valid target path.
It is also worth noting that AddToDecryptionBatch accepts path, that is, you can decrypt any item within any subfolder of the given IEncryptedDirectory.
Enumerating Items
Another typical task is enumerating items in container. First we will write a function, which prints contents of an encrypted directory, adding left indent for every recursive call.
void PrintDir(IEncryptedDirectory dir, String indent) throws Exception { System.out.println(indent + "<" + dir.GetName() + ">"); indent += " "; IEncryptedDirectory[] dirs = dir.GetDirectories(); for (IEncryptedDirectory chdir: dirs) PrintDir(chdir, indent); IEncryptedFile[] files = dir.GetFiles(); for (IEncryptedFile chfile: files) System.out.println(indent + chfile.GetName()); }
And here is a code snippet that uses the function above to print the container contents:
stor.Open(contPath, IEncryptedStorage.CONTAINER_ACCESS_MODE.CONT_READ_ONLY, null, new KeyCallback()); PrintDir(stor.GetRootDir(TARGET_DEFAULT), ""); stor.Close();
If you want to print the contents of a backup container, don't use TARGET_DEFAULT. Obtain the list of targets in the container (see IEncryptedFileStorage.GetRoots) and call PrintDir function separately for each target.