content: package im.actor.crypto.search;
  
  import im.actor.crypto.primitives.Digest;
  import im.actor.crypto.primitives.digest.SHA256;
  import im.actor.crypto.primitives.hmac.HMAC;
  
  public class SearchableWordDigest {
  
      public static SearchableWordDigest DEFAULT() {
          return new SearchableWordDigest(20, new SHA256());
      }
  
      private int splitValue;
      private Digest baseDigest;
  
      public SearchableWordDigest(int splitValue, Digest baseDigest) {
          if (splitValue > baseDigest.getDigestSize() - 8) {
              throw new IllegalArgumentException("Split value can't be bigger than digest size - 6 ");
          }
          this.splitValue = splitValue;
          this.baseDigest = baseDigest;
      }
  
      public byte[] digest(SearchableHashedWord word, byte[] random) {
          if (word.getWord().length != baseDigest.getDigestSize()) {
              throw new IllegalArgumentException("Word length MUST be equal to digest size");
          }
          if (random.length < splitValue) {
              throw new IllegalArgumentException("random length MUST be >= split value");
          }
  
          byte[] res = new byte[baseDigest.getDigestSize()];
          for (int i = 0; i < splitValue; i++) {
              res[i] = random[i];
          }
  
          HMAC hmac = new HMAC(word.getWordKey(), baseDigest);
          hmac.reset();
          hmac.update(res, 0, splitValue);
          byte[] dest = new byte[baseDigest.getDigestSize()];
          hmac.doFinal(dest, 0);
          for (int i = 0; i < baseDigest.getDigestSize() - splitValue; i++) {
              res[i + splitValue] = dest[i];
          }
          for (int i = 0; i < baseDigest.getDigestSize(); i++) {
              res[i] = (byte) (res[i] ^ word.getWord()[i]);
          }
          return res;
      }
  
      public boolean compare(byte[] digest, SearchableHashedWord queryWord) {
          if (queryWord.getWord().length != baseDigest.getDigestSize()) {
              throw new IllegalArgumentException("Word length MUST be equal to digest size");
          }
          byte[] tmp = new byte[baseDigest.getDigestSize()];
          for (int i = 0; i < baseDigest.getDigestSize(); i++) {
              tmp[i] = (byte) (digest[i] ^ queryWord.getWord()[i]);
          }
  
          HMAC hmac = new HMAC(queryWord.getWordKey(), baseDigest);
          hmac.update(tmp, 0, splitValue);
          byte[] dest = new byte[baseDigest.getDigestSize()];
          hmac.doFinal(dest, 0);
          for (int i = 0; i < baseDigest.getDigestSize() - splitValue; i++) {
              if (dest[i] != tmp[i + splitValue]) {
                  return false;
              }
          }
          return true;
      }
  }