All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dyadicsec.advapi.SDESessionKey Maven / Gradle / Ivy

Go to download

This is a collection of JAVA libraries that implement Unbound cryptographic classes for JAVA provider, PKCS11 wrapper, cryptoki, and advapi

There is a newer version: 42761
Show newest version
package com.dyadicsec.advapi;

import com.dyadicsec.pkcs11.CKException;
import com.dyadicsec.pkcs11.CKSecretKey;
import com.dyadicsec.pkcs11.DYCK_FPE_PARAMS;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.TimeZone;

/**
 * This class includes methods for application level encryption using a derived data encryption key (DEK)
 */
public class SDESessionKey
{
    private int purpose;
    CKSecretKey secretKey;
    SDEKey sdeKey;

    SDESessionKey(SDEKey sdeKey, int purpose, CKSecretKey secretKey)
    {
        this.sdeKey = sdeKey;
        this.purpose = purpose; this.secretKey = secretKey;
    }

    protected void finalize()
    {
        destroy();
    }

    public void destroy()
    {
        if (secretKey==null) return;
        try { secretKey.destroy(); } catch (CKException e) { }
        secretKey = null;
    }

    public byte[] getKeyMaterial()
    {
        try {  return secretKey.getValue(); } catch (CKException e) { return null; }
    }

    /**
     * Get the SDEKey used to derive this date encryption key
     * @return The SDEKey used for this data encryption key derivation
     */
    public SDEKey getSDEKey() { return sdeKey; }

    private static final int ONEWAY_TOKEN_SIZE = 16;

    /**
     * Creates a unique searchable token from a byte array
     * @param in The input data
     * @return Searchable token of size 16 bytes
     * @throws SecurityException In case of encryption error
     */
    public byte[] encryptPRF(byte[] in) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_ONE_WAY) throw new IllegalArgumentException("Invalid purpose");
        try { return secretKey.hmacSha256(in); }
        catch (CKException e) { throw new SecurityException(e); }
    }

    /**
     * Creates a unique searchable token from a byte array
     * @param data The input data
     * @return Searchable token of size 16 bytes
     * @throws SecurityException In case of encryption error
     */
    public String encryptPRF(final String data) throws SecurityException
    {
        try
        {
            byte[] encData = encryptPRF(data.getBytes("UTF8"));
            return SDEUtils.bytesToStringTP(encData);
        }
        catch (UnsupportedEncodingException e) { throw new SecurityException(e); }
    }

    private byte[] encryptTypePreserving(byte[] in, int bits) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_SP_ENC) throw new IllegalArgumentException("Invalid purpose");
        if ((in.length < 16) && ((bits % 2) != 0) && bits!=1) throw new IllegalArgumentException("Byte array input for type preserving encryption cannot be odd and less then 16 bytes");
        try { return secretKey.encryptSPE(in, bits); }
        catch (CKException e) { throw new SecurityException(e); }
    }

    /**
     * Encrypt a byte array
     * @param in The data to encrypt, the length of the array should be even or at least 16 bytes
     * @return The encrypted value, the size of the encrypted data equals to the size of the input
     * @throws SecurityException In case of encryption error
     */
    public byte[] encryptTypePreserving(byte[] in) throws SecurityException
    {
        return encryptTypePreserving(in, in.length*8);
    }

    private byte[] decryptTypePreserving(byte[] in, int bits) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_SP_ENC) throw new IllegalArgumentException("Invalid purpose");
        if ((in.length < 16) && ((bits % 2) != 0) && bits!=1) throw new IllegalArgumentException("Byte array input for type preserving decryption cannot be odd and less then 16 bytes");
        try { return secretKey.decryptSPE(in, bits); }
        catch (CKException e) { throw new SecurityException(e); }
    }

    /**
     * Decrypt a byte array
     * @param in The encrypted data
     * @return Decrryped byte array
     * @throws SecurityException In case of decryption error
     */
    public byte[] decryptTypePreserving(byte[] in) throws SecurityException
    {
        return decryptTypePreserving(in, in.length*8);
    }


    /**
     * Encrypt a string value
     * @param in The data to encrypt
     * @param BMPOnly Determines if the plain and cipher text includes only Unicode Basic Multilingual Plane codes
     *                or all Unicode planes. BMP plain should be suitable for most of the use cases and
     *                has a more compact byte representation. Set to false if the full set of Unicode codes is
     *                required. For more information on Unicode planes,
     *                see https://en.wikipedia.org/wiki/Plane_(Unicode)
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public String encryptTypePreserving(String in, boolean BMPOnly) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_STRING_ENC) throw new IllegalArgumentException("Invalid purpose");
        try
        {
            String format = BMPOnly ? "ISO-10646-UCS-2" : "UTF-16BE";
            return secretKey.encryptStringFPE(in, format);
        }
        catch (CKException e) { throw new SecurityException(e); }
    }

    /**
     * DEcrypt a string value
     * @param in The data to decrypt
     * @param BMPOnly Determines if the plain and cipher text includes only Unicode Basic Multilingual Plane codes
     *                or all Unicode planes. BMP plain should be suitable for most of the use cases and
     *                has a more compact byte representation. Set to false if the full set of Unicode codes is
     *                required. For more information on Unicode planes,
     *                see https://en.wikipedia.org/wiki/Plane_(Unicode)
     * @return Plain value
     * @throws SecurityException In case of encryption error
     */
    public String decryptTypePreserving(String in, boolean BMPOnly) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_STRING_ENC) throw new IllegalArgumentException("Invalid purpose");
        try
        {
            String format = BMPOnly ? "ISO-10646-UCS-2" : "UTF-16BE";
            return secretKey.decryptStringFPE(in, format);
        }
        catch (CKException e) { throw new SecurityException(e); }
    }

    /**
     * Encrypt a string value in order preserving form
     * @param data The data to encrypt
     * @param size Maximum size of values that should be compared with this value
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public String encryptOrderPreserving(String data, int size) throws SecurityException
    {
        try
        {
            byte[] dataBytes = data.getBytes("UTF8");
            dataBytes = SDEUtils.addTailing(dataBytes, (byte) 0, size - dataBytes.length);
            byte[] encData = encryptOPE(dataBytes);
            return SDEUtils.bytesToStringOP(encData);
        }
        catch (UnsupportedEncodingException e) { throw new SecurityException(e); }
    }

    /**
     * Decrypt a string value encrypted with order preserving encryption
     * @param encDataStr The encrypted value
     * @return String value in plain
     * @throws SecurityException In case of decryption error
     */
    public String decryptOrderPreserving(String encDataStr) throws SecurityException
    {
        try
        {
            byte[] encData = SDEUtils.stringToBytesOP(encDataStr);
            byte[] data = decryptOPE(encData);
            data = SDEUtils.removeTailing(data, (byte) 0);
            return new String(data, "UTF8");
        }
        catch (UnsupportedEncodingException e) { throw new SecurityException(e); }
    }


    byte[] encryptOPE(byte[] in) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_OP_ENC) throw new IllegalArgumentException("Invalid purpose");
        try { return secretKey.encryptOPE(in); }
        catch (CKException e) { throw new SecurityException(e); }
    }

    byte[] decryptOPE(byte[] in) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_OP_ENC) throw new IllegalArgumentException("Invalid purpose");
        try { return  secretKey.decryptOPE(in); }
        catch (CKException e) { throw new SecurityException(e); }
    }

    /**
     * Encrypt a long value
     * @param data The data to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public long encryptTypePreserving(long data) throws SecurityException
    {
        byte[] dataBytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(data).array();
        byte[] encData = encryptTypePreserving(dataBytes);
        ByteBuffer wrapped = ByteBuffer.wrap(encData); // big-endian by default
        return wrapped.getLong();
    }

    /**
     * Decrypt an encryptyed long value
     * @param encData The encrypted value
     * @return long value in plain
     * @throws SecurityException In case of decryption error
     */
    public long decryptTypePreserving(long encData) throws SecurityException
    {
        byte[] encDataBytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(encData).array();
        byte[] data = decryptTypePreserving(encDataBytes);
        ByteBuffer wrapped = ByteBuffer.wrap(data);
        return wrapped.getLong();
    }

    /**
     * Encrypt a integer value
     * @param data The data to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public int encryptTypePreserving(int data) throws SecurityException
    {
        byte[] dataBytes = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(data).array();
        byte[] encData = encryptTypePreserving(dataBytes);
        ByteBuffer wrapped = ByteBuffer.wrap(encData); // big-endian by default
        return wrapped.getInt();
    }

    /**
     * Decrypt an encryptyed integer value
     * @param encData The encrypted value
     * @return long value in plain
     * @throws SecurityException In case of decryption error
     */
    public int decryptTypePreserving(int encData) throws SecurityException
    {
        byte[] encDataBytes = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(encData).array();
        byte[] data = decryptTypePreserving(encDataBytes);
        ByteBuffer wrapped = ByteBuffer.wrap(data);
        return wrapped.getInt();
    }

    /**
     * Encrypt an integer value in order preserving form, encrypted value is of type long
     * @param data The data to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public long encryptOrderPreserving(int data) throws SecurityException
    {
        byte[] dataBytes = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(data).array();
        byte[] encData = encryptOPE(dataBytes);
        ByteBuffer wrapped = ByteBuffer.wrap(encData); // big-endian by default
        return wrapped.getLong();
    }

    /**
     * Decrypt an integer value encrypted with order preserving encryption
     * @param encData The encrypted value
     * @return Integer value in plain
     * @throws SecurityException In case of decryption error
     */
    public int decryptOrderPreserving(long encData) throws SecurityException
    {
        byte[] encDataBytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(encData).array();
        byte[] data = decryptOPE(encDataBytes);
        ByteBuffer wrapped = ByteBuffer.wrap(data); // big-endian by default
        return wrapped.getInt();
    }

    /**
     * Encrypt a short value
     * @param data The data to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public short encryptTypePreserving(short data) throws SecurityException
    {
        byte[] dataBytes = ByteBuffer.allocate(Short.SIZE / Byte.SIZE).putShort(data).array();
        byte[] encData = encryptTypePreserving(dataBytes);
        ByteBuffer wrapped = ByteBuffer.wrap(encData); // big-endian by default
        return wrapped.getShort();
    }

    /**
     * Decrypt an encryptyed short value
     * @param encData The encrypted value
     * @return String value in plain
     * @throws SecurityException In case of decryption error
     */
    public short decryptTypePreserving(short encData) throws SecurityException
    {
        byte[] encDataBytes = ByteBuffer.allocate(Short.SIZE / Byte.SIZE).putShort(encData).array();
        byte[] data = decryptTypePreserving(encDataBytes);
        ByteBuffer wrapped = ByteBuffer.wrap(data);
        return wrapped.getShort();
    }

    /**
     * Encrypt a short value in order preserving form, the return value is of type long
     * @param data The value to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public long encryptOrderPreserving(short data) throws SecurityException
    {
        return encryptOrderPreserving((int)data);
    }

    /**
     * Encrypt a float value
     * @param data The value to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public float encryptTypePreserving(float data) throws SecurityException
    {
        byte[] dataBytes = ByteBuffer.allocate(Float.SIZE / Byte.SIZE).putFloat(data).array();
        byte[] encData = encryptTypePreserving(dataBytes);
        ByteBuffer wrapped = ByteBuffer.wrap(encData);
        return wrapped.getFloat();
    }

    /**
     * Decrypt an encryptyed float value
     * @param encData The encrypted value
     * @return Float value in plain
     * @throws SecurityException In case of decryption error
     */
    public float decryptTypePreserving(float encData) throws SecurityException
    {
        byte[] encDataBytes = ByteBuffer.allocate(Float.SIZE / Byte.SIZE).putFloat(encData).array();
        byte[] data = decryptTypePreserving(encDataBytes);
        ByteBuffer wrapped = ByteBuffer.wrap(data);
        return wrapped.getFloat();
    }

    /**
     * Encrypt a double value
     * @param data The value to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public double encryptTypePreserving(double data) throws SecurityException
    {
        byte[] dataBytes = ByteBuffer.allocate(Double.SIZE / Byte.SIZE).putDouble(data).array();
        byte[] encData = encryptTypePreserving(dataBytes);
        ByteBuffer wrapped = ByteBuffer.wrap(encData);
        return wrapped.getDouble();
    }

    /**
     * Decrypt an encryptyed double value
     * @param encData The encrypted value
     * @return Double value in plain
     * @throws SecurityException In case of decryption error
     */
    public double decryptTypePreserving(double encData) throws SecurityException
    {
        byte[] encDataBytes = ByteBuffer.allocate(Double.SIZE / Byte.SIZE).putDouble(encData).array();
        byte[] data = decryptTypePreserving(encDataBytes);
        ByteBuffer wrapped = ByteBuffer.wrap(data);
        return wrapped.getDouble();
    }

    private static final int MS_PER_DAY = (1000 * 60 * 60 * 24);

    /**
     * Encrypt a Date value
     * @param data The data to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public java.sql.Date encryptTypePreserving(java.sql.Date data) throws SecurityException
    {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(data);

        Calendar utcCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));

        utcCal.set(Calendar.YEAR, calendar.get(Calendar.YEAR));
        utcCal.set(Calendar.MONTH, calendar.get(Calendar.MONTH));
        utcCal.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH));
        utcCal.set(Calendar.MILLISECOND, 0);
        utcCal.set(Calendar.SECOND, 0);
        utcCal.set(Calendar.MINUTE, 0);
        utcCal.set(Calendar.HOUR_OF_DAY, 0);

        long dateAsLongUTC = utcCal.getTimeInMillis();
        long d = dateAsLongUTC / MS_PER_DAY;
        //long e = d * MS_PER_DAY;

        byte[] dataBytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(d).array();

        SDEUtils.reverseBytes(dataBytes);
        dataBytes = Arrays.copyOf(dataBytes, 3); // we need only 3 bytes

        byte[] encData = encryptTypePreserving(dataBytes, 20);

        SDEUtils.reverseBytes(encData);
        byte[] longData = new byte[8];
        System.arraycopy(encData, 0, longData, 5, 3);

        ByteBuffer wrapped = ByteBuffer.wrap(longData);
        long output = wrapped.getLong() * MS_PER_DAY;
        return new java.sql.Date(output);
    }

    /**
     * Decrypt an encryptyed Date value
     * @param encData The encrypted value
     * @return Date value in plain
     * @throws SecurityException In case of decryption error
     */
    public java.sql.Date decryptTypePreserving(java.sql.Date encData) throws SecurityException
    {
        long dateAsLong = encData.getTime();
        long d = dateAsLong / MS_PER_DAY;
        byte[] encDataBytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(d).array();

        SDEUtils.reverseBytes(encDataBytes);
        encDataBytes = Arrays.copyOf(encDataBytes, 3); // we need only 3 bytes

        byte[] data = decryptTypePreserving(encDataBytes, 20);

        SDEUtils.reverseBytes(data);

        byte[] longData = new byte[8];
        System.arraycopy(data, 0, longData, 5, 3);
        ByteBuffer wrapped = ByteBuffer.wrap(longData);

        long output = wrapped.getLong();

        Calendar localCal = Calendar.getInstance();
        Calendar utcCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));

        utcCal.setTimeInMillis(output * MS_PER_DAY);
        localCal.setTimeInMillis(0); // Epoch
        localCal.set(Calendar.MILLISECOND, utcCal.get(Calendar.MILLISECOND));
        localCal.set(Calendar.SECOND, utcCal.get(Calendar.SECOND));
        localCal.set(Calendar.MINUTE, utcCal.get(Calendar.MINUTE));
        localCal.set(Calendar.HOUR_OF_DAY, utcCal.get(Calendar.HOUR_OF_DAY));
        localCal.set(Calendar.DAY_OF_MONTH, utcCal.get(Calendar.DAY_OF_MONTH));
        localCal.set(Calendar.MONTH, utcCal.get(Calendar.MONTH));
        localCal.set(Calendar.YEAR, utcCal.get(Calendar.YEAR));

        return new java.sql.Date(localCal.getTimeInMillis());
    }

    /**
     * Encrypt a Time value
     * @param data The data to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public java.sql.Time encryptTypePreserving(java.sql.Time data) throws SecurityException
    {
        Calendar localCal = Calendar.getInstance();
        localCal.setTime(data);

        Calendar utcCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
        utcCal.setTimeInMillis(0); // Epoch
        utcCal.set(Calendar.MILLISECOND, 0);
        utcCal.set(Calendar.SECOND, 0);
        utcCal.set(Calendar.MINUTE, localCal.get(Calendar.MINUTE));
        utcCal.set(Calendar.HOUR_OF_DAY, localCal.get(Calendar.HOUR_OF_DAY));

        //long timeAsLong = Math.round(cal.getTimeInMillis()/10f);
        long timeAsLong = utcCal.getTimeInMillis() / 1000 / 60;


        byte[] dataBytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(timeAsLong).array();

        SDEUtils.reverseBytes(dataBytes);
        dataBytes = Arrays.copyOf(dataBytes, 2); // we need only 3 bytes

        byte[] encData = encryptTypePreserving(dataBytes, 12);

        SDEUtils.reverseBytes(encData);
        byte[] longData = new byte[8];
        System.arraycopy(encData, 0, longData, 6, 2);

        ByteBuffer wrapped = ByteBuffer.wrap(longData);
        long output = wrapped.getLong() * 1000;
        return new java.sql.Time(output);
    }

    /**
     * Decrypt an encryptyed Time value
     * @param encData The encrypted value
     * @return Time value in plain
     * @throws SecurityException In case of decryption error
     */
    public java.sql.Time decryptTypePreserving(java.sql.Time encData) throws SecurityException
    {
        long timeAsLong = encData.getTime() / 1000;
        byte[] encDataBytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(timeAsLong).array();

        byte[] data = new byte[Long.SIZE / Byte.SIZE];
        SDEUtils.reverseBytes(encDataBytes);
        encDataBytes = Arrays.copyOf(encDataBytes, 2); // we need only 3 bytes

        data = decryptTypePreserving(encDataBytes, 12);

        SDEUtils.reverseBytes(data);
        byte[] longData = new byte[8];
        System.arraycopy(data, 0, longData, 6, 2);
        ByteBuffer wrapped = ByteBuffer.wrap(longData);

        long output = wrapped.getLong();
        //java.sql.Time time1 = new java.sql.Time(output * 100);


        Calendar localCal = Calendar.getInstance();
        Calendar utcCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));

        utcCal.setTimeInMillis(output * 1000 * 60);
        localCal.setTimeInMillis(0); // Epoch
        localCal.set(Calendar.MILLISECOND, 0);
        localCal.set(Calendar.SECOND, 0);
        localCal.set(Calendar.MINUTE, utcCal.get(Calendar.MINUTE));
        localCal.set(Calendar.HOUR_OF_DAY, utcCal.get(Calendar.HOUR_OF_DAY));

        java.sql.Time time = new java.sql.Time(localCal.getTime().getTime());
        return time;
    }

    /**
     * Encrypt a Timestamp value
     * @param data The data to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public java.sql.Timestamp encryptTypePreserving(java.sql.Timestamp data) throws SecurityException
    {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(data);

        Calendar utcCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));

        utcCal.set(Calendar.YEAR, calendar.get(Calendar.YEAR));
        utcCal.set(Calendar.MONTH, calendar.get(Calendar.MONTH));
        utcCal.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH));
        utcCal.set(Calendar.MILLISECOND, calendar.get(Calendar.MILLISECOND));
        utcCal.set(Calendar.SECOND, calendar.get(Calendar.SECOND));
        utcCal.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE));
        utcCal.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY));

        long dateAsLongUTC = utcCal.getTimeInMillis();

        byte[] dataBytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(dateAsLongUTC).array();


        SDEUtils.reverseBytes(dataBytes);
        dataBytes = Arrays.copyOf(dataBytes, 6);

        byte[] encData = encryptTypePreserving(dataBytes, 46);

        SDEUtils.reverseBytes(encData);
        byte[] longData = new byte[8];
        System.arraycopy(encData, 0, longData, 2, 6);
        ByteBuffer wrapped = ByteBuffer.wrap(longData);

        long output = wrapped.getLong();
        java.sql.Timestamp date = new java.sql.Timestamp(output);

        return date;
    }

    /**
     * Decrypt an encryptyed Timestamp value
     * @param encData The encrypted value
     * @return Timestamp value in plain
     * @throws SecurityException In case of decryption error
     */
    public java.sql.Timestamp decryptTypePreserving(java.sql.Timestamp encData) throws SecurityException
    {
        long dateAsLong = encData.getTime();
        byte[] encDataBytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(dateAsLong).array();

        SDEUtils.reverseBytes(encDataBytes);
        encDataBytes = Arrays.copyOf(encDataBytes, 6);

        byte[] data = decryptTypePreserving(encDataBytes, 46);

        SDEUtils.reverseBytes(data);
        byte[] longData = new byte[8];
        System.arraycopy(data, 0, longData, 2, 6);

        ByteBuffer wrapped = ByteBuffer.wrap(longData);

        long output = wrapped.getLong();

        Calendar localCal = Calendar.getInstance();
        Calendar utcCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));

        utcCal.setTimeInMillis(output);
        localCal.setTimeInMillis(0); // Epoch
        localCal.set(Calendar.MILLISECOND, utcCal.get(Calendar.MILLISECOND));
        localCal.set(Calendar.SECOND, utcCal.get(Calendar.SECOND));
        localCal.set(Calendar.MINUTE, utcCal.get(Calendar.MINUTE));
        localCal.set(Calendar.HOUR_OF_DAY, utcCal.get(Calendar.HOUR_OF_DAY));
        localCal.set(Calendar.DAY_OF_MONTH, utcCal.get(Calendar.DAY_OF_MONTH));
        localCal.set(Calendar.MONTH, utcCal.get(Calendar.MONTH));
        localCal.set(Calendar.YEAR, utcCal.get(Calendar.YEAR));

        java.sql.Timestamp date = new java.sql.Timestamp(localCal.getTimeInMillis());
        return date;
    }
    /**
     * Encrypt a Timestamp value in order preserving form, encrypted value is of string type
     * @param data The data to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public String encryptOrderPreserving(java.sql.Timestamp data) throws SecurityException
    {
        long time = data.getTime();
        int nanos = data.getNanos();

        ByteBuffer encDataBytesBuffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE + Integer.SIZE / Byte.SIZE);

        encDataBytesBuffer.putLong(0, time);
        encDataBytesBuffer.putInt(Long.SIZE / Byte.SIZE, nanos);

        byte[] dataBytes = encDataBytesBuffer.array();
        byte[] encData = encryptOPE(dataBytes);

        return SDEUtils.bytesToStringOP(encData);
    }

    /**
     * Decrypt a Timestamp value encrypted with order preserving encryption
     * @param encDataStr The encrypted value
     * @return Timestamp value in plain
     * @throws SecurityException In case of decryption error
     */
    public java.sql.Timestamp decryptOrderPreservingTS(String encDataStr) throws SecurityException
    {
        byte[] encData = SDEUtils.stringToBytesOP(encDataStr);

        byte[] data = decryptOPE(encData);

        ByteBuffer wrapped = ByteBuffer.wrap(data); // big-endian by default

        long time = wrapped.getLong(0);
        int nanos = wrapped.getInt(Long.SIZE / Byte.SIZE);
        java.sql.Timestamp ts = new java.sql.Timestamp(time);
        ts.setNanos(nanos);

        return ts;
    }

    /**
     * Encrypt a boolean value
     * @param data The data to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public boolean encryptTypePreserving(boolean data) throws SecurityException
    {
        byte[] in = new byte[1]; in[0]=data?(byte)1:(byte)0;
        return encryptTypePreserving(in, 1)[0]!=0;
    }

    /**
     * Decrypt an encryptyed boolean value
     * @param encData The encrypted value
     * @return Boolean value in plain
     * @throws SecurityException In case of decryption error
     */
    public boolean decryptTypePreserving(boolean encData) throws SecurityException
    {
        byte[] in = new byte[1]; in[0]=encData?(byte)1:(byte)0;
        return decryptTypePreserving(in, 1)[0]!=0;
    }

    /**
     * Encrypt a Blob value
     * @param data The data to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public java.sql.Blob encryptTypePreserving(java.sql.Blob data) throws SecurityException
    {
        try
        {
            byte[] enc = encryptTypePreserving(data.getBytes(1, (int)data.length()));
            return new javax.sql.rowset.serial.SerialBlob(enc);
        }
        catch (SQLException e) { throw new SecurityException(e); }
    }

    /**
     * Decrypt an encryptyed Blob value
     * @param encData The encrypted value
     * @return Blob value in plain
     * @throws SecurityException In case of decryption error
     */
    public java.sql.Blob decryptTypePreserving(java.sql.Blob encData) throws SecurityException
    {
        try
        {
            byte[] data = decryptTypePreserving(encData.getBytes(1, (int) encData.length()));
            return new javax.sql.rowset.serial.SerialBlob(data);
        }
        catch (SQLException e) { throw new SecurityException(e); }
    }

    /**
     * Encrypt a Clob value
     * @param data The data to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public java.sql.Clob encryptTypePreserving(java.sql.Clob data) throws SecurityException
    {
        try
        {
            String enc = encryptTypePreserving(data.getSubString(1, (int) data.length()), true);
            return new javax.sql.rowset.serial.SerialClob(enc.toCharArray());
        }
        catch (SQLException e) { throw new SecurityException(e); }
    }

    /**
     * Decrypt an encryptyed Clob value
     * @param encData The encrypted value
     * @return Clob value in plain
     * @throws SecurityException In case of decryption error
     */
    public java.sql.Clob decryptTypePreserving(java.sql.Clob encData) throws SecurityException
    {
        try
        {
            String data = decryptTypePreserving(encData.getSubString(1, (int) encData.length()), true);
            return new javax.sql.rowset.serial.SerialClob(data.toCharArray());
        }
        catch (SQLException e) { throw new SecurityException(e); }
    }

    /**
     * Encrypt a BigDecimal value
     * @param data The data to encrypt
     * @return Encrypted value
     * @throws SecurityException In case of encryption error
     */
    public java.math.BigDecimal encryptTypePreserving(java.math.BigDecimal data) throws SecurityException
    {
        try {
            int scale = data.scale();
            BigInteger bi = data.unscaledValue();
            boolean bNegative = bi.signum() == -1;
            bi = bi.abs();
            byte[] biBytes = bi.toByteArray();

            int biBytesLength = biBytes.length;
            if (biBytesLength > 12) {
                if ((biBytesLength == 13) && (biBytes[0] == 0)) {
                    // ok, ignore that
                    byte[] newBytes = new byte[12];
                    System.arraycopy(biBytes, 1, newBytes, 0, 12);
                    biBytes = newBytes;
                } else {
                    throw new IllegalArgumentException("Value encryption is not supported");
                }
            } else {
                biBytes = SDEUtils.addLeading(biBytes, (byte) 0, 12 - biBytesLength);
            }
//            if ((biBytesLength < 16) && ((biBytesLength % 2) != 0)) {
//                if (biBytes[0] < 0) {
//                    biBytes = addLeading(biBytes, (byte) -1, 1);
//                } else {
//                    biBytes = addLeading(biBytes, (byte) 0, 1);
//                }
//            }
            byte[] enc = encryptTypePreserving(biBytes);


//            enc = addLeading(enc, (byte) 1, 1); // make sure we wont have leading 0 on the byte array

            enc = SDEUtils.addLeading(enc, (byte) 0, 1);  // make it positive for sure
            BigInteger encBi = new BigInteger(enc);
            if (bNegative) {
                encBi = encBi.negate();
            }
            return new java.math.BigDecimal(encBi, scale);
        } catch (Exception e) {
            throw new SecurityException(e);
        }
    }

    /**
     * Decrypt an encryptyed BigDecimal value
     * @param encData The encrypted value
     * @return BigDecimal value in plain
     * @throws SecurityException In case of decryption error
     */
    public java.math.BigDecimal decryptTypePreserving(java.math.BigDecimal encData) throws SecurityException {
        try {
            int scale = encData.scale();
            BigInteger bi = encData.unscaledValue();
            boolean bNegative = bi.signum() == -1;
            bi = bi.abs();

            byte[] biBytes = bi.toByteArray();

            int biBytesLength = biBytes.length;
            if (biBytesLength > 12) {
                if ((biBytesLength == 13) && (biBytes[0] == 0)) {
                    // ok, ignore that
                    byte[] newBytes = new byte[12];
                    System.arraycopy(biBytes, 1, newBytes, 0, 12);
                    biBytes = newBytes;
                } else {
                    throw new IllegalArgumentException("Value encryption is not supported");
                }
            } else {
                biBytes = SDEUtils.addLeading(biBytes, (byte) 0, 12 - biBytesLength);
            }

//            if (biBytes[0] != 1) {
//                throw new IllegalArgumentException("Value was not decrypted with type preserving");
//            }
//            biBytes = removeLeading(biBytes, (byte) 1, true);

            byte[] data = decryptTypePreserving(biBytes);

            data = SDEUtils.addLeading(data, (byte) 0, 1);  // make it positive for sure
            BigInteger dataBi = new BigInteger(data);
            if (bNegative) {
                dataBi = dataBi.negate();
            }

//            BigInteger dataBi = new BigInteger(data);
            return new java.math.BigDecimal(dataBi, scale);
        } catch (Exception e) {
            throw new SecurityException(e);
        }
    }

    /**
     * Encrypt an email address in format preserving form, the encrypted value is also a legitimate email address
     * @param in Email address to encrypt
     * @param maxLen Maximum size of all email addresses encrypted
     * @return The encrypted value
     * @throws SecurityException In case of encryption error
     */
    public String encryptEMailAddress(String in, int maxLen) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_EMAIL_ENC) throw new IllegalArgumentException("Invalid purpose");
        try
        {
            byte[] inBuf = in.getBytes("UTF-8");
            byte[] outBuf = secretKey.encryptFPE(DYCK_FPE_PARAMS.DYCK_FPE_EMAIL, null, maxLen, inBuf);
            return new String(outBuf, "UTF-8");
        }
        catch (UnsupportedEncodingException e) { throw new SecurityException(e); }
        catch (CKException e) { throw new SecurityException(e); }
    }

    /**
     * Decrypt an encrypted email address, the encrypted value is also an email address
     * @param in The encrypted value
     * @return Original plain email address
     * @throws SecurityException In case of decryption error
     */
    public String decryptEMailAddress(String in) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_EMAIL_ENC) throw new IllegalArgumentException("Invalid purpose");
        try
        {
            byte[] inBuf = in.getBytes("UTF-8");
            byte[] outBuf = secretKey.decryptFPE(DYCK_FPE_PARAMS.DYCK_FPE_EMAIL, null, inBuf);
            return new String(outBuf, "UTF-8");
        }
        catch (UnsupportedEncodingException e) { throw new SecurityException(e); }
        catch (CKException e) { throw new SecurityException(e); }
    }

    /**
     * Encrypt a credit card number in format preserving form, the encrypted value is also a legitimate
     * credit card number
     * @param in Credit card number to encrypt
     * @return The encrypted value
     * @throws SecurityException In case of encryption error
     */
    public String encryptCreditCard(String in) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_CREDIT_CARD_ENC) throw new IllegalArgumentException("Invalid purpose");
        try
        {
            byte[] inBuf = in.getBytes("UTF-8");
            byte[] outBuf = secretKey.encryptFPE(DYCK_FPE_PARAMS.DYCK_FPE_CREDIT_CARD, null, 0, inBuf);
            if (outBuf==null)  throw new SecurityException("encryptCreditCard failed");
            return new String(outBuf, "UTF-8");
        }
        catch (UnsupportedEncodingException e) { throw new SecurityException(e); }
        catch (CKException e) { throw new SecurityException(e); }
    }

    public String encryptCreditCard(String in, String format) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_CREDIT_CARD_ENC) throw new IllegalArgumentException("Invalid purpose");
        try
        {
            byte[] inBuf = in.getBytes("UTF-8");
            byte[] outBuf = secretKey.encryptFPE(DYCK_FPE_PARAMS.DYCK_FPE_CREDIT_CARD, format.toCharArray(), 0, inBuf);
            if (outBuf==null)  throw new SecurityException("encryptCreditCard failed");
            return new String(outBuf, "UTF-8");
        }
        catch (UnsupportedEncodingException e) { throw new SecurityException(e); }
        catch (CKException e) { throw new SecurityException(e); }
    }
    /**
     * Decrypt a credit card number, the encrypted value is also a credit card number
     * @param in The encrypted value
     * @return Original plain email address
     * @throws SecurityException In case of decryption error
     */
    public String decryptCreditCard(String in) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_CREDIT_CARD_ENC) throw new IllegalArgumentException("Invalid purpose");
        try
        {
            byte[] inBuf = in.getBytes("UTF-8");
            byte[] outBuf = secretKey.decryptFPE(DYCK_FPE_PARAMS.DYCK_FPE_CREDIT_CARD, null, inBuf);
            return new String(outBuf, "UTF-8");
        }
        catch (UnsupportedEncodingException e) { throw new SecurityException(e); }
        catch (CKException e) { throw new SecurityException(e); }
    }

    public String decryptCreditCard(String in, String format) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_CREDIT_CARD_ENC) throw new IllegalArgumentException("Invalid purpose");
        try
        {
            byte[] inBuf = in.getBytes("UTF-8");
            byte[] outBuf = secretKey.decryptFPE(DYCK_FPE_PARAMS.DYCK_FPE_CREDIT_CARD, format.toCharArray(), inBuf);
            return new String(outBuf, "UTF-8");
        }
        catch (UnsupportedEncodingException e) { throw new SecurityException(e); }
        catch (CKException e) { throw new SecurityException(e); }
    }
    /**
     * Encrypt a US phone in format preserving form, the encrypted value is also a legitimate US phone number
     * @param in Email address to encrypt
     * @param format The output format, e.g. "###-###-####"
     * @return The encrypted value
     * @throws SecurityException In case of encryption error
     */
    public String encryptUSPhone(String in, String format) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_US_PHONE_ENC) throw new IllegalArgumentException("Invalid purpose");
        try
        {
            char[] formatChars = format==null ? null : format.toCharArray();
            byte[] inBuf = in.getBytes("UTF-8");
            byte[] outBuf = secretKey.encryptFPE(DYCK_FPE_PARAMS.DYCK_FPE_US_PHONE, formatChars, 0, inBuf);
            return new String(outBuf, "UTF-8");
        }
        catch (UnsupportedEncodingException e) { throw new SecurityException(e); }
        catch (CKException e) { throw new SecurityException(e); }
    }

    /**
     * Decrypt an encrypted US phone number, the encrypted value is also a US phone number
     * @param in The encrypted value
     * @param format The output format, e.g. "###-###-####"
     * @return Original plain US phone number
     * @throws SecurityException In case of decryption error
     */
    public String decryptUSPhone(String in, String format) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_US_PHONE_ENC) throw new IllegalArgumentException("Invalid purpose");
        try
        {
            char[] formatChars = format==null ? null : format.toCharArray();
            byte[] inBuf = in.getBytes("UTF-8");
            byte[] outBuf = secretKey.decryptFPE(DYCK_FPE_PARAMS.DYCK_FPE_US_PHONE, formatChars, inBuf);
            return new String(outBuf, "UTF-8");
        }
        catch (UnsupportedEncodingException e) { throw new SecurityException(e); }
        catch (CKException e) { throw new SecurityException(e); }
    }

    /**
     * Encrypt a SSN in format preserving form, the encrypted value is also a legitimate SSN
     * @param in SSN to encrypt
     * @param format The output format, e.g. "###-##-####"
     * @return The encrypted value
     * @throws SecurityException In case of encryption error
     */
    public String encryptSSN(String in, String format) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_SSN_ENC) throw new IllegalArgumentException("Invalid purpose");
        try
        {
            char[] formatChars = format==null ? null : format.toCharArray();
            byte[] inBuf = in.getBytes("UTF-8");
            byte[] outBuf = secretKey.encryptFPE(DYCK_FPE_PARAMS.DYCK_FPE_SSN, formatChars, 0, inBuf);
            return new String(outBuf, "UTF-8");
        }
        catch (UnsupportedEncodingException e) { throw new SecurityException(e); }
        catch (CKException e) { throw new SecurityException(e); }
    }

    /**
     * Decrypt an encrypted SSN, the encrypted value is also SSN
     * @param in The encrypted value
     * @param format The output format, e.g. "###-##-####"
     * @return Original plain SSN
     * @throws SecurityException In case of decryption error
     */
    public String decryptSSN(String in, String format) throws SecurityException
    {
        if (purpose!=SDEKey.PURPOSE_SSN_ENC) throw new IllegalArgumentException("Invalid purpose");
        try
        {
            char[] formatChars = format==null ? null : format.toCharArray();
            byte[] inBuf = in.getBytes("UTF-8");
            byte[] outBuf = secretKey.decryptFPE(DYCK_FPE_PARAMS.DYCK_FPE_SSN, formatChars, inBuf);
            return new String(outBuf, "UTF-8");
        }
        catch (UnsupportedEncodingException e) { throw new SecurityException(e); }
        catch (CKException e) { throw new SecurityException(e); }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy