edu.utdallas.bigsecret.crypter.CrypterMode2.java Source code

Java tutorial

Introduction

Here is the source code for edu.utdallas.bigsecret.crypter.CrypterMode2.java

Source

/**
* Copyright (c) 2013 The University of Texas at Dallas, Data Security and Privacy Lab. 
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 
* file except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed 
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific 
* language governing permissions and limitations under the License. See accompanying
* LICENSE file.
*/
package edu.utdallas.bigsecret.crypter;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.ArrayUtils;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.util.Bytes;

import edu.utdallas.bigsecret.cipher.Cipher;
import edu.utdallas.bigsecret.hash.Hasher;
import edu.utdallas.bigsecret.util.Utilities;

/**
 * This crypter is based on Model-2 of the BigSecret paper. <br>
 * It uses Hasher for the first four key-parts, and Cipher <br>
 * for the complete Key part and Value part. <br>
 * Here is the wrapping of each key-part <br>
 * row = H(row)<br>
 * fam = H(fam)<br>
 * qua = H(qua) || Ed(row||fam||qua||ts)<br>
 * ts = H(ts)<br>
 * val = Ep(val)
 */
public class CrypterMode2 extends CrypterBase {
    /**
     * Hasher for row.
     */
    private Hasher m_rowHasher;

    /**
     * Hasher for family.
     */
    private Hasher m_famHasher;

    /**
     * Hasher for qualifier.
     */
    private Hasher m_quaHasher;

    /**
     * Hasher for timestamp.
     */
    private Hasher m_tsHasher;

    /**
     * Cipher for the all key.
     */
    private Cipher m_keyCipher;

    /**
     * Cipher for the value part.
     */
    private Cipher m_valCipher;

    /**
     * Constructor for this class.
     * @param rowHasher Hasher for row key-part.
     * @param famHasher Hasher for family key-part.
     * @param quaHasher Hasher for qualifier key-part.
     * @param tsHasher Hasher for timestamp key-part.
     * @param keyCipher Cipher for the whole key.
     * @param valCipher Cipher for the value part.
     * @throws Exception Throws exception if any of the inputs is null.
     */
    public CrypterMode2(Hasher rowHasher, Hasher famHasher, Hasher quaHasher, Hasher tsHasher, Cipher keyCipher,
            Cipher valCipher) throws Exception {
        //check inputs
        if (rowHasher == null)
            throw new Exception("Row Hasher is null");
        else if (famHasher == null)
            throw new Exception("Family Hasher is null");
        else if (quaHasher == null)
            throw new Exception("Qualifier Hasher is null");
        else if (tsHasher == null)
            throw new Exception("Timestamp Hasher is null");
        else if (valCipher == null)
            throw new Exception("Value cipher is null");
        else if (keyCipher == null)
            throw new Exception("Key cipher is null");

        m_rowHasher = rowHasher;
        m_famHasher = famHasher;
        m_quaHasher = quaHasher;
        m_tsHasher = tsHasher;
        m_keyCipher = keyCipher;
        m_valCipher = valCipher;
    }

    /**
     * {@inheritDoc}
     */
    public void close() throws Exception {
    }

    /**
     * {@inheritDoc}
     */
    public byte[] getRowHash(byte[] data) throws Exception {
        //return row hasher's result
        return m_rowHasher.getHash(data);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] getIndexRowData(byte[] row) throws Exception {
        //check necessary inputs to this function
        if (row == null || row.length == 0)
            throw new Exception("Row data is null or has no data");

        //get bucket data and encode it in Base64.UrlSafe
        byte[] hashData = getRowHash(row);

        //return bucket data
        return hashData;
    }

    /**
     * {@inheritDoc}
     */
    public int getIndexRowDataSize() {
        //return total
        return m_rowHasher.hashSize();
    }

    /**
     * {@inheritDoc}
     */
    public byte[] wrapRow(KeyValue data) throws Exception {
        //call overloaded function
        return wrapRow(data.getRow(), null, null, 0, null);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] wrapRow(byte[] row, byte[] family, byte[] qualifier, long ts, byte[] value) throws Exception {
        //check necessary inputs to this function
        if (row == null || row.length == 0)
            throw new Exception("Row data is null or has no data");

        //concatenate bucket output with row cipher's encryption
        return getIndexRowData(row);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] unwrapRow(KeyValue data) throws Exception {
        //call overloaded function
        return unwrapRow(null, null, data.getQualifier(), 0, null);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] unwrapRow(byte[] row, byte[] family, byte[] qualifier, long ts, byte[] value) throws Exception {
        if (qualifier == null || qualifier.length == 0)
            throw new Exception("Qualifier data null or no data");

        int qualifierIndexSize = getIndexQualifierDataSize();
        byte[] completeData = m_keyCipher.decrypt(qualifier, qualifierIndexSize);

        int rowSize = Bytes.toInt(completeData, 0, 4);

        return ArrayUtils.subarray(completeData, 12, 12 + rowSize);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] getFamilyHash(byte[] data) throws Exception {
        //return family hasher's result
        return m_famHasher.getHash(data);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] getIndexFamilyData(byte[] family) throws Exception {
        return Base64.encodeBase64URLSafe(getFamilyHash(family));
    }

    /**
     * {@inheritDoc}
     */
    public int getIndexFamilyDataSize() {
        int hashOutputSize = m_famHasher.hashSize();

        return ((hashOutputSize * 8) + 5) / 6;
    }

    /**
     * {@inheritDoc}
     */
    public byte[] wrapFamily(KeyValue data) throws Exception {
        //call overloaded function
        return wrapFamily(null, data.getFamily(), null, 0, null);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] wrapFamily(byte[] row, byte[] family, byte[] qualifier, long ts, byte[] value) throws Exception {
        //check necessary inputs to this function
        if (family == null || family.length == 0)
            throw new Exception("Family data is null or has no data");

        //just encrypt family data
        return getIndexFamilyData(family);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] unwrapFamily(KeyValue data) throws Exception {
        //call overloaded function
        return unwrapFamily(null, null, data.getQualifier(), 0, null);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] unwrapFamily(byte[] row, byte[] family, byte[] qualifier, long ts, byte[] value)
            throws Exception {
        if (qualifier == null || qualifier.length == 0)
            throw new Exception("Qualifier data null or no data");

        int qualifierIndexSize = getIndexQualifierDataSize();
        byte[] completeData = m_keyCipher.decrypt(qualifier, qualifierIndexSize);

        int rowSize = Bytes.toInt(completeData, 0, 4);
        int famSize = Bytes.toInt(completeData, 4, 4);

        return ArrayUtils.subarray(completeData, 12 + rowSize, 12 + rowSize + famSize);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] getQualifierHash(byte[] data) throws Exception {
        //return qualifier hasher's result on data
        return m_quaHasher.getHash(data);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] getIndexQualifierData(byte[] qualifier) throws Exception {
        //check necessary inputs to this function
        if (qualifier == null || qualifier.length == 0)
            throw new Exception("Qualifier data is null or has no data");

        //get bucket data
        byte[] hashValue = getQualifierHash(qualifier);

        //return bucket value
        return hashValue;
    }

    /**
     * {@inheritDoc}
     */
    public int getIndexQualifierDataSize() {
        return m_quaHasher.hashSize();
    }

    /**
     * {@inheritDoc}
     */
    public byte[] wrapQualifier(KeyValue data) throws Exception {
        return wrapQualifier(data.getRow(), data.getFamily(), data.getQualifier(), data.getTimestamp(), null);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] wrapQualifier(byte[] row, byte[] family, byte[] qualifier, long ts, byte[] value)
            throws Exception {
        if (row == null || row.length == 0)
            throw new Exception("Row is null or has no data");
        else if (family == null || family.length == 0)
            throw new Exception("Family is null or has no data");
        else if (qualifier == null || qualifier.length == 0)
            throw new Exception("Qualifier is null or has no data");

        byte[] qualifierIndex = getIndexQualifierData(qualifier);

        byte[] sizeArray = Bytes.toBytes(row.length);
        sizeArray = ArrayUtils.addAll(sizeArray, Bytes.toBytes(family.length));
        sizeArray = ArrayUtils.addAll(sizeArray, Bytes.toBytes(qualifier.length));

        byte[] completeData = ArrayUtils.addAll(sizeArray, row);
        completeData = ArrayUtils.addAll(completeData, family);
        completeData = ArrayUtils.addAll(completeData, qualifier);
        completeData = ArrayUtils.addAll(completeData, Bytes.toBytes(ts));

        completeData = m_keyCipher.encrypt(completeData);

        return ArrayUtils.addAll(qualifierIndex, completeData);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] unwrapQualifier(KeyValue data) throws Exception {
        return unwrapQualifier(null, null, data.getQualifier(), 0, null);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] unwrapQualifier(byte[] row, byte[] family, byte[] qualifier, long ts, byte[] value)
            throws Exception {
        if (qualifier == null || qualifier.length == 0)
            throw new Exception("Qualifier data null or no data");

        int qualifierIndexSize = getIndexQualifierDataSize();
        byte[] completeData = m_keyCipher.decrypt(qualifier, qualifierIndexSize);

        int rowSize = Bytes.toInt(completeData, 0, 4);
        int famSize = Bytes.toInt(completeData, 4, 4);
        int quaSize = Bytes.toInt(completeData, 8, 4);

        return ArrayUtils.subarray(completeData, 12 + rowSize + famSize, 12 + rowSize + famSize + quaSize);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] getTimestampHash(long data) throws Exception {
        return m_tsHasher.getHash(Bytes.toBytes(data));
    }

    /**
     * {@inheritDoc}
     */
    public byte[] getIndexTimestampData(long timestamp) throws Exception {
        return getTimestampHash(timestamp);
    }

    /**
     * {@inheritDoc}
     */
    public int getIndexTimestampDataSize() {
        //actually normal size of timestampindex is m_bucketizer.size().
        //but we append bucket value with 0
        //final index data has size 8
        return 8;
    }

    /**
     * {@inheritDoc}
     */
    public long wrapTimestamp(KeyValue data) throws Exception {
        //call overloaded function
        return wrapTimestamp(null, null, null, data.getTimestamp(), null);
    }

    /**
     * {@inheritDoc}
     */
    public long wrapTimestamp(byte[] row, byte[] family, byte[] qualifier, long ts, byte[] value) throws Exception {
        //get bucket result
        byte[] tsHashResult = getIndexTimestampData(ts);

        //return long representation of the concatenation
        return Utilities.getLong(tsHashResult);
    }

    /**
     * {@inheritDoc}
     */
    public long unwrapTimestamp(KeyValue data) throws Exception {
        //call overloaded function
        return unwrapTimestamp(null, null, data.getQualifier(), 0, null);
    }

    /**
     * {@inheritDoc}
     */
    public long unwrapTimestamp(byte[] row, byte[] family, byte[] qualifier, long ts, byte[] value)
            throws Exception {
        if (qualifier == null || qualifier.length == 0)
            throw new Exception("Qualifier data null or no data");

        int qualifierIndexSize = getIndexQualifierDataSize();
        byte[] completeData = m_keyCipher.decrypt(qualifier, qualifierIndexSize);

        int rowSize = Bytes.toInt(completeData, 0, 4);
        int famSize = Bytes.toInt(completeData, 4, 4);
        int quaSize = Bytes.toInt(completeData, 8, 4);

        return Bytes.toLong(ArrayUtils.subarray(completeData, 12 + rowSize + famSize + quaSize,
                12 + rowSize + famSize + quaSize + 8));
    }

    /**
     * {@inheritDoc}
     */
    public byte[] encryptValue(byte[] data) throws Exception {
        //return value cipher's result on data
        return m_valCipher.encrypt(data);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] decryptValue(byte[] data) throws Exception {
        //return value cipher's result on data
        return m_valCipher.decrypt(data);
    }

    /**
     * {@inheritDoc}
     */
    public byte[] wrapValue(KeyValue data) throws Exception {
        return wrapValue(null, null, null, 0, data.getValue());
    }

    /**
     * {@inheritDoc}
     */
    public byte[] wrapValue(byte[] row, byte[] family, byte[] qualifier, long ts, byte[] value) throws Exception {
        if (value == null || value.length == 0)
            throw new Exception("Value is null or has no data");

        byte[] encVal = encryptValue(value);

        return encVal;
    }

    /**
     * {@inheritDoc}
     */
    public byte[] unwrapValue(KeyValue data) throws Exception {
        return unwrapValue(null, null, null, 0, data.getValue());
    }

    /**
     * {@inheritDoc}
     */
    public byte[] unwrapValue(byte[] row, byte[] family, byte[] qualifier, long ts, byte[] value) throws Exception {
        if (value == null || value.length == 0)
            throw new Exception("Value is null or has no data");

        return decryptValue(value);
    }
}