class="markdown_views prism-tomorrow-night">
Hill2密码
Hill2密码的加密、解密、破译
概述
- 选择二阶加密矩阵A
- 将明文字母依次按每两个一组查出其表值。得到一组二维向量{åi}
- 通过加密矩阵得到{βi},而 {βi}=Aαi(mod26)
- 查向量βi的字母表值,及得到密文
- 利用加密矩阵的逆矩阵,由密文得到明文αi=A−1βi
- 命题 整数a有m逆元 的充要条件为a与m无公共素因子
- 命题 矩阵A模m可逆<=>|A|与m无公共素因子,例子详见P6
注意细节
模m逆
设
a∈Zm,若存在
b∈Zm使得
b=a−1(mod m),称
a 有模
m的逆,记作
b = a−1(mod m)。
命题
整数
a有模
m逆元的充要条件为
a与
m无公共素因子
模26倒数表
模m逆矩阵
代码实现(java)
使用第三方库ujmp
package hill;
import org.ujmp.core.Matrix;
public class Hill2 {
final static String table = new String("ZABCDEFGHIJKLMNOPQRSTUVWXY");
public static void main(String[] args) {
String message = new String("ourmarshalwasshot");
int[][] tmp = {{1,2},{0,3}};
Matrix A = Matrix.Factory.importFromArray(tmp);
Matrix Ainv = calDecodeKey(A);
StringBuffer cipher = encodeORdecode(message,A);
System.out.println(cipher);
StringBuffer decodedMessage = encodeORdecode(cipher.toString(), Ainv);
System.out.println(decodedMessage);
String cipher1 = "OJWPISWAZUXAUUISEABAUCRSIPLBHAAMMLPJJOTENH";
Matrix decodeKey = Hill2attack("UCRS", "TACO");
StringBuffer plaintext = encodeORdecode(cipher1, decodeKey);
System.out.print(plaintext);
}
public static StringBuffer encodeORdecode(String message, Matrix keyAorAinv) {
int[][][] messagenum;
messagenum = mesToArry(message,2,1);
Matrix[] matresult = new Matrix[messagenum.length];
int[][] numresultmp;
int[] numresult = new int[messagenum.length*2];
Matrix[] matmessage = new Matrix[messagenum.length];
for (int i = 0; i < messagenum.length; i++) {
matmessage[i]= Matrix.Factory.importFromArray(messagenum[i]);
matresult[i] = keyAorAinv.mtimes(matmessage[i]);
numresultmp = matresult[i].toIntArray();
while(numresultmp[0][0]<0) {
numresultmp[0][0]+=26;
}
while(numresultmp[1][0]<0) {
numresultmp[1][0]+=26;
}
numresult[i*2] = numresultmp[0][0]%26;
numresult[i*2+1] = numresultmp[1][0]%26;
}
StringBuffer result = new StringBuffer(" ");
for (int i = 0; i < numresult.length; i++) {
result.append(table.charAt(numresult[i]));
}
result.deleteCharAt(0);
return result;
}
public static Matrix Hill2attack(String knownCipher, String knownPlain) {
Matrix decodeKey;
int[][][] cipherArry = mesToArry(knownCipher,2,2);
int[][][] plainArry = mesToArry(knownPlain,2,2);
Matrix cipherMat = Matrix.Factory.importFromArray(cipherArry[0]);
cipherMat = cipherMat.transpose();
Matrix plainMat = Matrix.Factory.importFromArray(plainArry[0]);
plainMat = plainMat.transpose();
int detCipherMat = (int)cipherMat.det();
int detCipherMatinv = extendEuclid(26, detCipherMat);
Matrix comCipherMat = companionMatrix(cipherMat);
comCipherMat = comCipherMat.times(detCipherMatinv);
comCipherMat = matModm(comCipherMat, 26);
decodeKey = plainMat.mtimes(comCipherMat);
decodeKey = matModm(decodeKey, 26);
return decodeKey;
}
public static int[][][] mesToArry(String message,int rowNum, int columNum){
while (message.length()%(columNum*rowNum)==1) {
message = message + message.charAt(message.length()-1);
}
message = message.toUpperCase();
int[][][] messagenum = new int[message.length()/(columNum*rowNum)][rowNum][columNum];
for (int i = 0; i < message.length(); i++) {
int tmp0 = i/(columNum*rowNum);
int tmp1 = (i-(i/(columNum*rowNum))*(columNum*rowNum))/columNum;
int tmp2 = (i-(i/(columNum*rowNum))*(columNum*rowNum))%columNum;
messagenum[tmp0][tmp1][tmp2 ] = table.indexOf(message.charAt(i));
}
return messagenum;
}
public static int extendEuclid(int e, int modValue){
int D = 0;
int x1, x2, x3, y1, y2, y3, t1, t2, t3;
x1 = y2 = 1;
x2 = y1= 0;
x3 = e;
y3 = modValue;
int q = 0;
while(true){
if(y3 == 1){
D = y2;
break;
}
if(y3 == 0){
D = y2;
break;
}
q = x3 / y3;
t1 = x1 - q*y1;
t2 = x2 - q*y2;
t3 = x3 - q*y3;
x1 = y1;
x2 = y2;
x3 = y3;
y1 = t1;
y2 = t2;
y3 = t3;
}
return D<0?e+D:D;
}
public static Matrix calDecodeKey(Matrix encodeKeyA) {
Matrix decodeKeyAinv;
int Adet = (int)encodeKeyA.det();
int AdetInv = extendEuclid(26, Adet);
decodeKeyAinv = companionMatrix(encodeKeyA);
decodeKeyAinv = decodeKeyAinv.times(AdetInv);
decodeKeyAinv = matModm(decodeKeyAinv, 26);
return decodeKeyAinv;
}
public static Matrix companionMatrix(Matrix A) {
return A.inv().times(A.det());
}
public static Matrix matModm(Matrix A, int m) {
int[][] comCipherArry = A.toIntArray();
for (int i = 0; i < comCipherArry.length; i++) {
for (int j = 0; j < comCipherArry[i].length; j++) {
while(comCipherArry[i][j]<0)
comCipherArry[i][j] += m;
comCipherArry[i][j] %= m;
}
}
Matrix AModM = Matrix.Factory.importFromArray(comCipherArry);
return AModM;
}
}