package SecureBase; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.client.*; import javax.crypto.Cipher; import javax.crypto.spec.*; import java.security.*; import java.util.*; import java.io.IOException; public class Cryptor { byte[] tableDigest; /** * Sets up the MessageDigest Object which can be updated according * to the row provided by the put object * @param tableDigest */ public Cryptor(byte[] tableDigest) { this.tableDigest = tableDigest; } /** * Encrypts a Put object * @param putToEncrypt * @return Put EncryptedObject */ public Put encrypt(final Put putToEncrypt) { if(putToEncrypt == null) return null; MessageDigest md; Put encryptedPut = new Put(putToEncrypt.getRow(),putToEncrypt.getTimeStamp(),putToEncrypt.getRowLock()); encryptedPut.setWriteToWAL(putToEncrypt.getWriteToWAL()); try { md = MessageDigest.getInstance("MD5"); md.update(tableDigest); md.update(putToEncrypt.getRow()); byte[] rowDigest = md.digest(); byte[] familyDigest; byte[] qualDigest; byte[] timestampDigest; for(Map.Entry<byte [], List<KeyValue>> entry : putToEncrypt.getFamilyMap().entrySet()) { md.reset(); md.update(rowDigest); md.update(entry.getKey()); familyDigest = md.digest(); for(KeyValue kv: entry.getValue()) { md.reset(); md.update(familyDigest); md.update(kv.getQualifier()); qualDigest = md.digest(); md.reset(); md.update(qualDigest); md.update(Bytes.toBytes(kv.getTimestamp())); timestampDigest = md.digest(); SecretKeySpec key = new SecretKeySpec(timestampDigest,"AES"); Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding"); c.init(Cipher.ENCRYPT_MODE, key); byte encrypted[] = c.doFinal(kv.getValue()); encryptedPut.add(entry.getKey(), kv.getQualifier(), kv.getTimestamp(), encrypted); } } return encryptedPut; } catch (Exception e) { e.printStackTrace(); System.out.println(e.getMessage()); } return encryptedPut; } /** * Decrypts a Result Object * @param resultToDecrypt * @return */ public Result decrypt(final Result resultToDecrypt) { if(resultToDecrypt == null) return null; KeyValue[] KVS = resultToDecrypt.raw(); KeyValue[] decryptedKVS = new KeyValue[KVS.length]; int i = 0; for(KeyValue KV : KVS) { decryptedKVS[i++] = decrypt(KV); } return new Result(decryptedKVS); } /** * Decrypts a KeyValue Object * @param keyvalueToDecrypt * @return */ public KeyValue decrypt(KeyValue kvToDecrypt) { MessageDigest md; try { md = MessageDigest.getInstance("MD5"); md.update(tableDigest); md.update(kvToDecrypt.getRow()); byte[] rowDigest = md.digest(); byte[] familyDigest; byte[] qualDigest; byte[] timestampDigest; md.reset(); md.update(rowDigest); md.update(kvToDecrypt.getFamily()); familyDigest = md.digest(); md.reset(); md.update(familyDigest); md.update(kvToDecrypt.getQualifier()); qualDigest = md.digest(); md.reset(); md.update(qualDigest); md.update(Bytes.toBytes(kvToDecrypt.getTimestamp())); timestampDigest = md.digest(); SecretKeySpec key = new SecretKeySpec(timestampDigest,"AES"); Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding"); c.init(Cipher.DECRYPT_MODE, key); byte decrypted[] = c.doFinal(kvToDecrypt.getValue()); return new KeyValue(kvToDecrypt.getRow(),kvToDecrypt.getFamily(),kvToDecrypt.getQualifier(),kvToDecrypt.getTimestamp(),decrypted); } catch (Exception e) { e.printStackTrace(); return null; } } public static KeyValue decryptCell(byte[] qualHash, KeyValue kv) { MessageDigest md; try { md = MessageDigest.getInstance("MD5"); md.update(qualHash); md.update(Bytes.toBytes(kv.getTimestamp())); byte[] timestampDigest = md.digest(); SecretKeySpec key = new SecretKeySpec(timestampDigest,"AES"); Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding"); c.init(Cipher.DECRYPT_MODE, key); byte decrypted[] = c.doFinal(kv.getValue()); return new KeyValue(kv.getRow(),kv.getFamily(),kv.getQualifier(),kv.getTimestamp(),decrypted); } catch (Exception e) { e.printStackTrace(); return null; } } }