zoukankan      html  css  js  c++  java
  • 信息安全--仿射密码

    说明

    加法密码和乘法密码结合就构成仿射密码,仿射密码的加密和解密算法是:

    密钥:k = (m, n)
    C = Ek(m) = (k1*m + k2) mod n ;
    M = Dk(c) = k3(c-k2) mod n (其中(k3×k1) mod 26 = 1);
    

    仿射密码具有可逆性的条件是:
    gcd(k1, n)=1. 当 k1=1 时,仿射密码变为加法密码,当 k2=0 时,仿射密码变为乘法密码。
    仿射密码中的密钥空间的大小为 nφ(n),当 n 为 26 字母,φ(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) 的逆元,则记 (b)(a^{-1} mod n) 看了上面的定义, 我们知道:
    只有当 (a)(n) 互素的时候, (a) 才是有模逆的.
    其他情况下是不存在模逆的, 比如 2 对 26 就没有模逆.

    求模逆的方法

    利用计算机的强大运算能力从 2 穷举;
    另外一种巧妙的方法 ---- 扩展欧几里德变换

    java 代码实现

    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
         */
    
  • 相关阅读:
    ognl的应用1
    未命名
    flash钟表的实现
    文本显示输入字数
    HttpServlet session的用法: (2)
    $.fx与$.fn.fx 区别
    javascript 事件冒泡 和 冒泡事件阻止
    (function($){...})(jQuery) 含义
    选择城市插件 jQuery
    offset().left 用法
  • 原文地址:https://www.cnblogs.com/zishu/p/8650214.html
Copyright © 2011-2022 走看看