2014-04-20 19 views
1

我在Java Android中实现小山密码算法时遇到了一些问题。它在一定条件下运行良好,但在其他条件下缺乏。我的小山密码有什么问题? (Java Android)

这是正在运行的应用程序。

1.运行就OK了以下条件

**Ok for below input**

2.它配备了意想不到的结果为以下状态

the problem comes here

我只是盘算,问题来自消极的结果。我使用行列式和乘法反向来找到矩阵求逆。

这里是我的项目代码。

MainActivity.java

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 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz?!.,"; 
    //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 < 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() < 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 < 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 < array_kunci.length){ 

     //masukkan masing-masing nilai ke matriks kunci 
     for (int x=0; x < 2; x++){ 
      for (int y=0; y<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< str_length/2 ; b++){ 
     for(int j=0; j<2; j++){ 
      for(int x=0; x<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<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&&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< str_length/2 ; b++){ 
     for(int j=0; j<2; j++){ 
      for(int x=0; x<2 ; x++){ 
       c[i] += key_invers[j][x]*p[x+zz]; 
      } 
      i++; 
     } 
     zz += 2; 
    } 
    return c; 
} 

现在我怀疑的问题来自于行列式,MI(乘法逆)和getInverse功能。我真的希望有人能帮我找出我的代码或算法有什么问题。

毕竟我真的很感谢你的关注和帮助我的意图。非常感谢你们。如果我的代码有点混乱,我很抱歉,因为在这个问题上我仍然是初学者。

回答

0

从WIKIPAGE http://en.wikipedia.org/wiki/Hill_cipher

并非所有的矩阵具有逆(见可逆矩阵)。当且仅当它的行列式不为零时,矩阵才会有逆,并且与模块基数没有任何公因式。因此,如果我们以上述模26为基础,行列式必须是非零的,并且不能被2或13整除。如果行列式为0,或者与模数基有共同的因子,那么该矩阵不能用于Hill密码,并且必须选择另一个矩阵(否则将不可能解密)。幸运的是,满足希尔密码使用条件的矩阵相当普遍。

“abay”不是小山密码的有效密钥。

SORRY因为没有仔细阅读你的代码。

尝试改变

mod_result[i] = Math.abs(num_cipher[i]%67); 

mod_result[i] = (((num_cipher[i]%67) + 67)%67); 

mod_result[i] = num_cipher[i]%67; 
if(mod_result[i] <0){ 
    mod_result[i] += 67; 
} 
+0

谢谢您的回答,伙计。但是在这种情况下,我不是在模26上工作,我使用了67个字符,因为我们知道它是一个素数。它是否保持相同的条件?或者你可以告诉我,一定不能被一个有效的数字整除...... – rizqieroway