Search code examples
javaencryptionlotus-domino

Encrypting string in java - Lotus Domino Integration (Netpay)


I have a tricky problem within my Lotus Domino application. We have been using EPDQ to handle payments for our shopping cart but customer wants to switch to Netpay which works differently in that you encrypt your own transaction information using their encryption key and initialisation vector. They helpfully provided some sample java, the encrytion function from this is below but although Lotus Domino was OK importing the libraries needed for the encryption;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;

It could not resolve the last library I need

import org.apache.commons.codec.binary.Hex;

My Java skills aren't great but my understanding is that all this seems to be doing is generating a byte string for the encryption process. There is a matching decryption function which also needs this library, is there another alternative way of achieving its effect? In my agent you can import loads of different libraries but none so far contain what I need.

public static String encrypt_cbc(String input, String key, String iv){
    byte[] crypted = null;
    try{
         //byte[] key_byte = Hex.decodeHex(key.toCharArray());
         byte[] key_byte = DatatypeConverter.parseHexBinary(key); 
         SecretKeySpec key_spec = new SecretKeySpec(key_byte, "AES");

         //byte[] iv_byte = Hex.decodeHex(iv.toCharArray());
         byte[] iv_byte = DatatypeConverter.parseHexBinary(IV); 
         IvParameterSpec iv_spec = new IvParameterSpec(iv_byte);

         Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

         cipher.init(Cipher.ENCRYPT_MODE, key_spec, iv_spec);
         crypted = cipher.doFinal(input.getBytes());

    }catch(Exception e){
         System.out.println(e.toString());
    }
    String crypted_hex = Hex.encodeHexString(crypted);
    return crypted_hex;
}

Thursday 21:13 - Honing in on a solution, replacing Hex.decodeHex with DatatypeConverter.parseHexBinary seems like a good start although its not liking the call to cipher.init or doFinal so still have work to do. I've not yet gone down the path of incorporating an additional JAR to my Domino Designer as from many years of experience sharing servers, its usually best possible to make do with configuration provided to you, I've got a call into Bluesky Hosting but aren't hopeful.


Solution

  • Turned out to have a very simple answer, DatatypeConverter.parseHexBinary(key) was able to create the desired byte stream for the encryption process. This time though I had no problem with the required import javax.xml.bind.DatatypeConverter which was accessible without needing any config changes to my Domino 8.5.3 designer client.

    public static String encrypt_cbc(String input, String key, String iv){
        byte[] crypted = null;
        try{
             //byte[] key_byte = Hex.decodeHex(key.toCharArray());
             byte[] key_byte = DatatypeConverter.parseHexBinary(key); 
             SecretKeySpec key_spec = new SecretKeySpec(key_byte, "AES");
    
             //byte[] iv_byte = Hex.decodeHex(iv.toCharArray());
             byte[] iv_byte = DatatypeConverter.parseHexBinary(iv); 
             IvParameterSpec iv_spec = new IvParameterSpec(iv_byte);
    
             Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    
             cipher.init(Cipher.ENCRYPT_MODE, key_spec, iv_spec);
             crypted = cipher.doFinal(input.getBytes());
    
        }catch(Exception e){
             System.out.println(e.toString());
        }
        //String crypted_hex = Hex.encodeHexString(crypted);
        String crypted_hex = DatatypeConverter.printHexBinary(crypted);
        return crypted_hex;
    }
    

    Its then very easy to use this to build the html form which is submitted to Netpay.

    out.print("<input type=\"hidden\" name=\"username\" value=\"");
    out.println(encrypt_cbc(username, key, iv) + "\" />");
    

    or where data to be encrypted is numeric

    out.print("<input type=\"hidden\" name=\"amount\" value=\""); 
    out.println(encrypt_cbc(orderTotal.toString(), key, iv) + "\" />");
    

    My understanding of Java encryption is still fairly high level but that isn't hugely important as above code works great and is more than fast enough for its intended purpose.