// Path: src/main/java/com/healthmarketscience/jackcess/crypt/InvalidCredentialsException.java
// public class InvalidCredentialsException extends IllegalStateException
// {
//   private static final long serialVersionUID = 20170130L;
// 
//   public InvalidCredentialsException(String msg) {
//     super(msg);
//   }
// 
// }
// 
// Path: src/main/java/com/healthmarketscience/jackcess/crypt/util/StreamCipherCompat.java
// public interface StreamCipherCompat 
// {
//   public String getAlgorithmName();
// 
//   public void init(boolean forEncryption, CipherParameters params);
// 
//   public byte returnByte(byte in);
// 
//   public int processStreamBytes(byte[] in, int inOff,
//                                 int len, byte[] out, int outOff);
// 
//   public void reset();
// }


import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.params.KeyParameter;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.function.Supplier;
import com.healthmarketscience.jackcess.crypt.InvalidCredentialsException;
import com.healthmarketscience.jackcess.crypt.util.StreamCipherCompat;
import com.healthmarketscience.jackcess.impl.ByteUtil;
import com.healthmarketscience.jackcess.impl.CodecHandler;
import com.healthmarketscience.jackcess.impl.ColumnImpl;
import com.healthmarketscience.jackcess.impl.DatabaseImpl;
import com.healthmarketscience.jackcess.impl.JetFormat;
import com.healthmarketscience.jackcess.impl.PageChannel;
        }
      };
  }

  @Override
  protected KeyParameter computeCipherParams(int pageNumber) {
    return new KeyParameter(
        applyPageNumber(_baseHash, PASSWORD_DIGEST_LENGTH, pageNumber));
  }

  @Override
  protected int getMaxEncodedPage() {
    return MSISAM_MAX_ENCRYPTED_PAGE;
  }

  private void verifyPassword(ByteBuffer buffer, byte[] testEncodingKey,
                              byte[] testBytes)
  {
    StreamCipherCompat engine = decryptInit(getStreamCipher(),
                                      new KeyParameter(testEncodingKey));

    byte[] encrypted4BytesCheck = getPasswordTestBytes(buffer);
    if(isBlankKey(encrypted4BytesCheck)) {
      // no password?
      return;
    }

    byte[] decrypted4BytesCheck = decryptBytes(engine, encrypted4BytesCheck);

    if (!Arrays.equals(decrypted4BytesCheck, testBytes)) {
// Path: src/main/java/com/healthmarketscience/jackcess/crypt/InvalidCredentialsException.java
// public class InvalidCredentialsException extends IllegalStateException
// {
//   private static final long serialVersionUID = 20170130L;
// 
//   public InvalidCredentialsException(String msg) {
//     super(msg);
//   }
// 
// }
// 
// Path: src/main/java/com/healthmarketscience/jackcess/crypt/util/StreamCipherCompat.java
// public interface StreamCipherCompat 
// {
//   public String getAlgorithmName();
// 
//   public void init(boolean forEncryption, CipherParameters params);
// 
//   public byte returnByte(byte in);
// 
//   public int processStreamBytes(byte[] in, int inOff,
//                                 int len, byte[] out, int outOff);
// 
//   public void reset();
// }


// Path: src/main/java/com/healthmarketscience/jackcess/crypt/impl/MSISAMCryptCodecHandler.java
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.params.KeyParameter;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.function.Supplier;
import com.healthmarketscience.jackcess.crypt.InvalidCredentialsException;
import com.healthmarketscience.jackcess.crypt.util.StreamCipherCompat;
import com.healthmarketscience.jackcess.impl.ByteUtil;
import com.healthmarketscience.jackcess.impl.CodecHandler;
import com.healthmarketscience.jackcess.impl.ColumnImpl;
import com.healthmarketscience.jackcess.impl.DatabaseImpl;
import com.healthmarketscience.jackcess.impl.JetFormat;
import com.healthmarketscience.jackcess.impl.PageChannel;

        }
      };
  }

  @Override
  protected KeyParameter computeCipherParams(int pageNumber) {
    return new KeyParameter(
        applyPageNumber(_baseHash, PASSWORD_DIGEST_LENGTH, pageNumber));
  }

  @Override
  protected int getMaxEncodedPage() {
    return MSISAM_MAX_ENCRYPTED_PAGE;
  }

  private void verifyPassword(ByteBuffer buffer, byte[] testEncodingKey,
                              byte[] testBytes)
  {
    StreamCipherCompat engine = decryptInit(getStreamCipher(),
                                      new KeyParameter(testEncodingKey));

    byte[] encrypted4BytesCheck = getPasswordTestBytes(buffer);
    if(isBlankKey(encrypted4BytesCheck)) {
      // no password?
      return;
    }

    byte[] decrypted4BytesCheck = decryptBytes(engine, encrypted4BytesCheck);

    if (!Arrays.equals(decrypted4BytesCheck, testBytes)) {
      throw new InvalidCredentialsException("Incorrect password provided");