package com.airlock.iam.security.util.crypto;

import com.airlock.iam.security.util.SeededSecureRandom;
import com.google.common.base.Preconditions;
import com.google.common.primitives.Bytes;
import java.security.SecureRandom;
import java.util.Arrays;

public class OneBlockRandomnessPrepender implements Cipher {
   private static final SecureRandom PRNG = SeededSecureRandom.getInstance();
   private final Cipher cipher;

   public OneBlockRandomnessPrepender(Cipher cipher) {
      this.cipher = (Cipher)Preconditions.checkNotNull(cipher);
   }

   @Override
   public CipherText encrypt(byte[] plaintext, KeyAndIV parameters) throws EncryptionException {
      return this.cipher.encrypt(this.prependRandomBlock(plaintext), parameters);
   }

   private byte[] prependRandomBlock(byte[] plaintext) {
      byte[] randomBlock = this.generateRandomBlock();
      return Bytes.concat(new byte[][]{randomBlock, plaintext});
   }

   private byte[] generateRandomBlock() {
      byte[] randomBlock = new byte[this.cipher.blockSizeInBytes()];
      PRNG.nextBytes(randomBlock);
      return randomBlock;
   }

   @Override
   public byte[] decrypt(CipherText ciphertext, KeyAndIV parameters) throws DecryptionException {
      return this.removeRandomBlock(this.cipher.decrypt(ciphertext, parameters));
   }

   private byte[] removeRandomBlock(byte[] plaintext) {
      return Arrays.copyOfRange(plaintext, this.cipher.blockSizeInBytes(), plaintext.length);
   }

   @Override
   public boolean isSuitablePrefix(String prefix) {
      return this.cipher.isSuitablePrefix(prefix);
   }

   @Override
   public int blockSizeInBytes() {
      return this.cipher.blockSizeInBytes();
   }
}
