1. 程式人生 > >信息安全--仿射密碼

信息安全--仿射密碼

crypt href pre express spa end lower fin 因此

說明:

加法密碼和乘法密碼結合就構成仿射密碼,仿射密碼的加密和解密算法是:
C=Ek(m)=(k1m+k2) mod n ;
M= Dk(c)=k3(c- k2) mod n (其中(k3 ×k1)mod26 = 1);

仿射密碼具有可逆性的條件是:
gcd(k1, n)=1. 當k1=1時,仿射密碼變為加法密碼,當k2=0時,仿射密碼變為乘法密碼。
仿射密碼中的密鑰空間的大小為nφ(n),當n26字母,φ(n)=12,因此仿射密碼的密鑰空間為12×26 = 312

加密舉例:

設密鑰K= (7, 3), 用仿射密碼加密明文hot。 三個字母對應的數值是71419
分別加密如下:

(7×7 + 3) mod 26 = 52 mod 26 =0
(7×14 + 3) mod 26 = 101 mod 26 =23
(7×19 + 3) mod 26 =136 mod 26 =6

三個密文數值為0236,對應的密文是AXG

解密舉例:

先來引入一個定義.
  大家知道, 好多東西都有逆, 大家讀小學時都知道,兩個數相乘乘機為1,則互為倒數, 其實是最簡單的逆.
  後來, 我們到了高中, 我們學習了逆函數;
  到了大學, 我們學習線性代數,知道兩個矩陣的乘積為單位矩陣的話,則這兩個矩陣互為逆矩陣.   現在我跟大家介紹另一種逆. 叫模逆. 其實很好理解的,
  如下:
  若a,b兩數的乘積對正整數n取模的結果為1. 則稱a,b互為另外一個的模逆.
  比如:

  3*7 = 21; 21 % 20 = 1 ; 所以3,7 互為 20 的 模逆.
  9*3 = 27; 27 % 26 = 1 ; 所以9,3 互為 26 的 模逆.

如何標記? 若a,b互為n的模逆 , 即ba的模n的逆元,則記ba-1mod n看了上面的定義, 我們知道:
只有當an互素的時候,a才是有模逆的.
其他情況下是不存在模逆的, 比如226就沒有模逆.

求模逆的方法:

利用計算機的強大運算能力從2窮舉

另外一種巧妙的方法 ---- 擴展歐幾裏德變換

java代碼實現:

package com.jiangbiao.firsthomework;

import java.util.Scanner;

/**
 * 仿射密碼的加密和解密
 * n = 26
 */
public class AffineCipher {

    //n
    public
static final int n = 26; public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.println("請輸入密鑰k1:"); int k1 = input.nextInt(); System.out.println("請輸入密鑰k2:"); int k2 = input.nextInt(); Scanner input2 = new Scanner(System.in); System.out.println("請輸入明文:"); String express = input2.nextLine(); //加密 String ciphertext; ciphertext = encryptionOperation(k1, k2, express); System.out.println("密文:" + ciphertext); //解密 String decrypttext = Decrypt(k1, k2, ciphertext); System.out.println("解密結果:" + decrypttext); } /** * 加密:C= Ek(m)=(k1m+k2) mod n * @param k1 * @param k2 * @param express * @return */ public static String encryptionOperation(int k1, int k2, String express){ //轉化成小寫並去除空格 String express2 = express.toLowerCase().replaceAll(" ", ""); System.out.println("express2:" + express2); char[] expressChar = express2.toCharArray(); int[] jiamiChar = new int[express2.length()]; //將字母轉換成數字表示 for (int i=0;i<express2.length();i++){ jiamiChar[i] = ((expressChar[i] - 97) * k1 + k2) % n; //97 = a System.out.print(jiamiChar[i] + " "); } //拼湊密文 StringBuffer miwen = new StringBuffer(); for(int j=0;j<jiamiChar.length;j++){ miwen = miwen.append((char)(jiamiChar[j] + 65)); } return miwen.toString(); } /** * 解密 * @param k1 * @param k2 * @param ciphertext * @return */ public static String Decrypt(int k1, int k2, String ciphertext){ //1.求出k3 { (k3 * k1) mod 26 = 1 }: int k3 = 0; for (int i = 2;;i++){ if((i*k1) % n == 1){ k3 = i; break; } } System.out.println("k3:" + k3); //求出明文 { M= Dk(c)=k3(c- k2) mod n } StringBuffer mingwen = new StringBuffer(); for (int j=0;j<ciphertext.length();j++){ int c = ((k3 * (ciphertext.charAt(j) - 65 - k2))) % 26; if (c < 0){ c = c + 26; } mingwen.append((char)( c + 65)); } return mingwen.toString(); } }
/**
     * 示例1:
     請輸入密鑰k1:
     7
     請輸入密鑰k2:
     3
     請輸入明文:
     hot
     express2:hot
     0 23 6 密文:AXG
     k3:15
     解密結果:HOT
     */

    /**
     * 示例2:
     請輸入密鑰k1:
     11
     請輸入密鑰k2:
     7
     請輸入明文:
     MXJFDEDD
     express2:mxjfdedd
     9 0 2 10 14 25 14 14 密文:JACKOZOO
     k3:19
     解密結果:MXJFDEDD
     */

信息安全--仿射密碼