Loading…

Kryptel/Java

Parcel Decryption Example

Decrypting a Silver Key Parcel

This example shows how to use ISilverKeyExtractor interface for decrypting a Silver Key parcel created in the previous example.

In order to reduce unrelated code as much as possible, this example uses a hard-wired password and hard-wired file paths. A real-life program must never use a hard-wired password as that makes encryption pretty useless.

import static com.kryptel.Guids.CID_SILVER_KEY;
import static com.kryptel.Guids.IID_ISilverKeyExtractor;

import java.io.File;
import java.util.UUID;

import com.kryptel.bslx.BooleanFlag;
import com.kryptel.IKeyCallback;
import com.kryptel.IKryptelComponent;
import com.kryptel.INotification;
import com.kryptel.IProgressCallback;
import com.kryptel.IReplaceCallback;
import com.kryptel.KeyIdent;
import com.kryptel.KeyRecord;
import com.kryptel.Loader;
import com.kryptel.Message;
import com.kryptel.Message.Code;
import com.kryptel.ProgressCallback;
import com.kryptel.silver_key.ISilverKeyExtractor;

As in the parcel creation example, the first step is implementing the required callback interfaces. Note that all callbacks except IKeyCallback are optional; you can specify null as the callback argument if the corresonding callback function is not needed.

Our implementation of IKeyCallback remains the same except the slightly different assert operator. Again, we use a pre-defined password to make the implementing class simpler.

class KeyCallback implements IKeyCallback {
  private static final String PREDEFINED_PASSWORD = "qwerty";

  public KeyRecord Callback(Object arg,
                            String prompt,
                            int allowed,
                            UUID expected) throws Exception {
    assert (expected.equals(KeyIdent.IDENT_PASSWORD));    // Password expected
    KeyRecord kr = new KeyRecord();
    kr.keyMaterial = KeyIdent.IDENT_PASSWORD;
    kr.password = PREDEFINED_PASSWORD;
    return kr;
  }
}

The progress callback implementation is the same as in the previous example. Check the Parcel Creation example for implementation notes.

class Progress implements ProgressCallback.IProgressDialog {
  public void CreateProgress(Object arg,
    String strTitle,
    boolean totalBar,
    BooleanFlag abortRequested) {
  }

  public void SetProgressMessage(Object arg, String strMessage) {
    System.out.print(strMessage + "  ");
  }

  public void SetProgressStep(Object arg, int fileStep, int totalStep) {
    if (fileStep == IProgressCallback.PROGRESS_STEPS)
      System.out.println("  Done!");
  }

  public void DismissProgress(Object arg) { }
}

The next three callbacks are extractor-specific. IReplaceCallback simply prints the name of the replaced file. The default behavior is also REPLACE_ACTION.REPLACE, so specifying null instead of this callback would have the same effect (except printing the file name).

class ReplaceCallback implements IReplaceCallback {
  public REPLACE_ACTION Callback(Object arg,
                                 StringBuilder newFileName,
                                 long newSize, long newDate,
                                 String oldFilePath,
                                 long oldSize, long oldDate) throws Exception {
    File f = new File(oldFilePath);
    System.out.println(" (Replacing " + f.getName() + ") ");
    return IReplaceCallback.REPLACE_ACTION.REPLACE;
  }
}

ISilverKeyExtractor.IMessage implementation will be called for both the unencrypted parcel description and for all the encrypted messages.

class MessageCallback implements ISilverKeyExtractor.IMessage {
  public boolean Show(String parcelTitle, String message) {
    System.out.println("\n======================================================");
    System.out.println(message);
    System.out.println("======================================================\n");
    return true;
  }
}

Our INotification implementation prints the notification in three angle brackets.

class NotificationCallback implements INotification {
  public void ShowNotification(Code code) {
    System.out.println("<<<" + Message.Get(code) + ">>>");
  }

  public void DismissNotification() { }
}

And here is the code of the main program:

public class SkTest {

  private static final String PARCEL_TITLE = "Test Parcel";

  public static void main(String[] args) {
    try {
      IKryptelComponent skComp = (IKryptelComponent)Loader.CreateComponent(CID_SILVER_KEY);
      ISilverKeyExtractor sk = (ISilverKeyExtractor)skComp.GetInterface(IID_ISilverKeyExtractor);

      sk.ExtractData("C:\\SkTest", 
                     "C:\\SkTest\\Parcel.sk",
                     null,
                     new KeyCallback(),
                     new ProgressCallback("Decryption progress", new Progress(), null),
                     new ReplaceCallback(),
                     new MessageCallback(),
                     new NotificationCallback());

      ISilverKeyExtractor.ParcelStatistics stat = sk.GetExtractionStatistics();
      System.out.println("\nDecrypted " + stat.nFilesCreated + " files");
      System.out.println("Created " + stat.nDirsCreated + " directories");
      System.out.println("Total " + stat.bytesWritten + " bytes written");
    }
    catch (Exception ex) {
      System.out.println(ex.toString());
    }
  }
}

As you can see, parcel decryption code can't be simpler and actually does not need any explanation. Let's see what result we will get running this program:

Checking parcel integrity...    Done!
  Done!
  
======================================================
This is a test Silver key parcel containing a few files,
a directory tree, and a couple of encrypted messages.
======================================================

<<<Verifying password...>>>
Detecting parcel tampering...    Done!
  Done!

======================================================
Processing a couple of files
======================================================

Targets.docx  Capture.png    Done!

======================================================
Processing a directory subtree
======================================================

  Done!
  Done!

Decrypted 4 files
Created 1 directories
Total 117065 bytes written

Note that because of progress bar optimization, the progress bar operations are not strictly linear and may skip small files. They are optimized for GUI dialogs, and are not well fit for simple printing implementation as above.