信息安全--仿射密码

Posted SinatJ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了信息安全--仿射密码相关的知识,希望对你有一定的参考价值。

说明:

加法密码和乘法密码结合就构成仿射密码,仿射密码的加密和解密算法是:
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的模逆 , 即b 为a的模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
     */

 

以上是关于信息安全--仿射密码的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JAVA 中编写仿射密码解密的逻辑?

仿射密码解密,输出大小写不同

Python:解码使用仿射密码编码的 Vigenere 密码

简单的加密与解密的实现---仿射密码

uva1339Ancient Cipher

简单的加密与解密的实现---仿射密码(c++使用string)