title: What's wrong with my hill cipher code? (Java Android)
body: <p>I have some problems in implementing the hill cipher algorithm in Java Android. It runs well on certain condition but it comes lack on other condition.</p>
  
  <p>Here is the running app.</p>
  
  <p><strong>1. It runs OK for below condition</strong></p>
  
  <p><img src="https://i.stack.imgur.com/o3dGn.png" alt="**Ok for below input**"></p>
  
  <p><strong>2. It comes with unexpected result for below condition</strong></p>
  
  <p><img src="https://i.stack.imgur.com/f9JXL.png" alt="the problem comes here"></p>
  
  <p>I'm just figuring that the problem comes from the negative results. I used the determinant and multiplicative invers to find the matrix invers.</p>
  
  <p>here is the code of my project.</p>
  
  <p><strong>MainActivity.java</strong></p>
  
  <pre><code>package com.andri.hilltest;
  
  import java.util.Arrays;
  
  import android.os.Bundle;
  import android.app.Activity;
  import android.view.Menu;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.widget.Button;
  import android.widget.EditText;
  import android.widget.Toast;
  
  public class MainActivity extends Activity implements OnClickListener {
  
      EditText txtPlain, txtKey, txtCipher, txtDecrypt;
      Button btnEncrypt, btnCheck, btnDecrypt;
      String char_db = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ?!.,";
      //String char_db = "ABCDEFGHIJKLMNOPQRSTUVWXYZabc";
      int[] array_angka, array_angka2;
      int[] array_angka_cipher, array_angka_decrypted;
  
  
  
  int[][] M_key = new int[2][2];
  int[][] M_inverse = new int [2][2];
  int i;
  String key_input, ciphertext, plaintext;
  int db_length = char_db.length();
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
  
  
      txtPlain = (EditText) findViewById(R.id.txtPlain);
      txtKey = (EditText) findViewById(R.id.txtKey);
      txtCipher = (EditText) findViewById(R.id.txtCipher);
      txtDecrypt = (EditText) findViewById(R.id.txtDecrypt);
  
  
      btnEncrypt = (Button) findViewById(R.id.btnEncrypt);
      btnDecrypt = (Button) findViewById(R.id.btnDecrypt);
      btnCheck = (Button) findViewById(R.id.btnCheck);
  
      btnEncrypt.setOnClickListener(this);
      btnCheck.setOnClickListener(this);
      btnDecrypt.setOnClickListener(this);
  }
  
  @Override
  public void onClick(View v) {
      if(v == btnEncrypt){
  
          String plainTextInput = txtPlain.getText().toString();
  
          char[] array_huruf = plainTextInput.toCharArray();
  
          if(array_huruf.length%2!=0)
              array_angka = new int[array_huruf.length+1];
          else
              array_angka = new int[array_huruf.length];
  
          for (i=0 ; i &lt; array_huruf.length ; i++){
  
              int posisi_huruf =  char_db.indexOf(array_huruf[i]);
  
              //Toast.makeText(this, "Tombol ditekan " +  posisi_huruf , Toast.LENGTH_SHORT).show();
              array_angka[i] = posisi_huruf; //if I disable this line the code should run well
          }
  
  
  
          //jika panjang array ganjil letakkan spasi diakhir array
          if(array_huruf.length % 2 != 0 ){
              array_angka[array_huruf.length] = 62;
          }
  
  
  
          array_angka_cipher = new int[array_angka.length];
  
          array_angka_cipher = encrypt_hill(M_key, array_angka);
  
          ciphertext = to_char(array_angka_cipher);
          txtCipher.setText(Arrays.toString(array_angka) +"\n\n" + Arrays.toString(array_angka_cipher) + "\n\n" + to_char(array_angka_cipher) );
  
  
      }
  
      else if (v == btnCheck){
          key_input = txtKey.getText().toString(); 
  
          if (key_input.length() &lt; 4)
              Toast.makeText(this, "panjang kunci harus 4 karakter!" , Toast.LENGTH_SHORT).show();
          else{
              check_kunci(key_input);
          }
      }
  
      else if(v == btnDecrypt){
          char[] array_cipher = ciphertext.toCharArray();
          array_angka2 = new int[array_cipher.length];
  
          for (i=0 ; i &lt; array_cipher.length ; i++){
  
              int posisi_huruf =  char_db.indexOf(array_cipher[i]);
              array_angka2[i] = posisi_huruf; 
          }
  
          array_angka_decrypted = new int[array_cipher.length];
          array_angka_decrypted = decrypt_hill(M_inverse, array_angka2);
  
          plaintext = to_char(array_angka_decrypted);
  
          txtDecrypt.setText(Arrays.toString(array_angka2) + "\n\n" + Arrays.toString(array_angka_decrypted) + "\n\n" + plaintext);
      }
  }
  
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.main, menu);
      return true;
  }
  
  public void check_kunci(String kunci){
  
      Toast.makeText(this, kunci  , Toast.LENGTH_SHORT).show();
  
      char[] array_kunci = kunci.toCharArray();
  
      int j = 0;
  
      while ( j &lt; array_kunci.length){
  
          //masukkan masing-masing nilai ke matriks kunci
          for (int x=0; x &lt; 2; x++){
              for (int y=0; y&lt;2; y++){
                  M_key[x][y] = char_db.indexOf(array_kunci[j]);
                  j = j+1;
              }
          }
      }
      Toast.makeText(this, "hello " + M_key[0][0] + " " + M_key[0][1] + " " + M_key[1][0] + " " + M_key[1][1]   , Toast.LENGTH_SHORT).show();
  
      int det = determinant(M_key);
      Toast.makeText(this, " determinant = " + det   , Toast.LENGTH_SHORT).show();
      if (det == 0){
          Toast.makeText(this, "Kunci invalid karena determinant = 0"   , Toast.LENGTH_SHORT).show();
      } else if (det%67==0){
          Toast.makeText(this, "Kunci invalid karena determinan memiliki persamaan faktor dgn 67"   , Toast.LENGTH_SHORT).show();
      } else {
          Toast.makeText(this, "Kunci Valid, multiplication inverse " + mi(det)   , Toast.LENGTH_SHORT).show();
  
          M_inverse = getInverse(M_key, mi(det));
          Toast.makeText(this, "Inverse berhasil" + M_inverse[0][0] + " " + M_inverse[0][1] + " " + M_inverse[1][0] + " " + M_inverse[1][1]  , Toast.LENGTH_SHORT).show();
  
          String tampil_banding = M_key[0][0] + " " + M_key[0][1] + " " + M_key[1][0] + " " + M_key[1][1] +"\n\n" + M_inverse[0][0] + " " + M_inverse[0][1] + " " + M_inverse[1][0] + " " + M_inverse[1][1];
  
          txtCipher.setText(tampil_banding);
      }
  
  
  }
  
  public int[] encrypt_hill(int[][] key, int[] p){
      int str_length;
      str_length = txtPlain.length();
  
      if(str_length%2!=0)
          str_length = str_length+1;
  
      int[] c = new int[str_length];
      int i = 0;
      int zz = 0;
  
      for (int b=0; b&lt; str_length/2 ; b++){
          for(int j=0; j&lt;2; j++){
              for(int x=0; x&lt;2 ; x++){
                  c[i] += key[j][x]*p[x+zz];
              }
              i++;
          }
          zz += 2;
      }
      return c;
  }
  
  private String to_char(int[] num_cipher){
      int[] mod_result = new int[num_cipher.length];
  
      char[] parse_cipher = new char[num_cipher.length];
  
      for(int i=0;i&lt;num_cipher.length;i++){
          mod_result[i] = Math.abs(num_cipher[i]%67);
          parse_cipher[i] = char_db.charAt(mod_result[i]);
      }
  
      String cipher_result = new String(parse_cipher);
  
      return cipher_result;
  }
  
  public int determinant(int[][] A){
  
      int res;
  
      res = A[0][0]*A[1][1] - A[1][0]*A[0][1];
  
      return res;
  }
  
  
  
  public int[][] getInverse(int key[][], int mi){
      int[][] key_inv = new int[2][2];
  
      key_inv[0][0] = ((key[1][1]*mi)%67);
      key_inv[0][1] = (((-1*key[0][1])*mi)%67);
      key_inv[1][0] = (((-1*key[1][0])*mi)%67);
      key_inv[1][1] = ((key[0][0]*mi)%67);
  
      return key_inv;
  
  }
  
  public int mi(int d)
  {
      int q,r1,r2,r,t1,t2,t;
      r1=67;
      r2=d;
      t1=0;
      t2=1;
  
      while(r1!=1&amp;&amp;r2!=0)
      {
          q=r1/r2;
          r=r1%r2;
          t=t1-(t2*q);
          r1=r2;
          r2=r;
          t1=t2;
          t2=t;
      }
  
      return (t1+t2);
  }
  
  public int[] decrypt_hill(int[][] key_invers, int[] p){
      int str_length;
      str_length = txtPlain.length();
  
      if(str_length%2!=0)
          str_length = str_length+1;
  
      int[] c = new int[str_length];
      int i = 0;
      int zz = 0;
  
      for (int b=0; b&lt; str_length/2 ; b++){
          for(int j=0; j&lt;2; j++){
              for(int x=0; x&lt;2 ; x++){
                  c[i] += key_invers[j][x]*p[x+zz];
              }
              i++;
          }
          zz += 2;
      }
      return c;
  }
  </code></pre>
  
  <p>For now I'm suspecting that the problem comes from the determinant, mi (multiplicative inverse) and getInverse function. I really hope someone out there could help me to find out what's wrong with my code or my algorithm. </p>
  
  <p>After all I really appreciate your attentions and intentions to help me. Thank you very much guys. I'm sorry if my code a little bit messy, because I'm still a beginner in this matters. </p>