【密码学原理与实践】(三)仿射密码 符java代码实现

仿射密码(Affine Cipher)

转载请著明出处

仿射密码是代换密码的一种特殊情况。

在学习仿射密码之前我们首先需要了解几个定理

定理

同余方程唯一解定理

a Zm,对任意的b∈Zm,同余方程ax b (mod m)有唯一解x∈Zm的充分必要条件是gcd(a, m) = 1*.*

证明:假设gcd(a,m)=d>1,则同余方程ax=0(modm)至少有两个解,分别是x=0和x=m/d。这种情况下e(x)=(ax+b)modm不是一个单射函数,因此不能用了作为一个有效的加密函数。

有了如上的定理我们就很快能判断一个函数是否是有效的加密函数,比如gcd(26,2)=2那么4x+7不是一个有效的加密函数。因为对任意的x∈Z26,x和x+13将被加密成相同的密文。

接下来我们看一下仿射密码的秘钥空间,因为26=2×13,所以所有与26互素的数为a= 1 3 5 7 9 11 15 17 19 21 23 25而b可能是Z26中的任何数,因此仿射密码的秘钥空间为12×26=312.由此也可以看出仿射密码是很不安全的。

欧拉函数和欧拉定理

a 1*,* m 2. 如果 gcd(a, m) = 1, 则称a与m互素。Zm中所有域m互素元素个数用φ(m)来表示(函数φ也称为欧拉函数)

在这里插入图片描述

以一个通俗的式子来说明欧拉定理:

φ(72)=φ(23×32)=23-1(2-1)×32-1(3-1)=22×1×3×2=24

乘法逆

设a∈ Zm,若存在a∈Zm,使得aa1(mod m),则称a模m可逆,a为a的(乘法)逆元,a可记为a-1 mod m,在m固定的情形下,简记为a-1

由之前的结论可知,a在Zm上存在乘法逆,当且仅当gcd(a,m)=1,并且其逆如果存在,则必唯一。

在Z26的情形下,与26互素的乘法逆如下表所示:

原数 1 3 5 7 11 17 25
1 9 21 15 19 23 25

仿射密码

令P=C=Z26,且K={(a,b)∈Z26×Z26 :gcd(a,26)=1}对任意的k=(a,b)∈K, x,y属于Z26,定义ek(x)=(ax+b)mod26和dk(y)=a-1(y-b)mod 26

代码实现

package com.slp.cryptography;

import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName AffineCipher
 * @Description 仿射密码
 * @Author sanglp
 * @Date 2020/11/30 14:43
 * @Version 1.0
 **/
public class AffineCipher {
    
    
    static Map<Integer,Integer> reverseMap = new HashMap<Integer,Integer>();
    static{
    
    
        reverseMap.put(1,1);
        reverseMap.put(3,9);
        reverseMap.put(9,3);
        reverseMap.put(5,21);
        reverseMap.put(21,5);
        reverseMap.put(7,15);
        reverseMap.put(15,7);
        reverseMap.put(11,19);
        reverseMap.put(19,11);
        reverseMap.put(17,23);
        reverseMap.put(23,17);
        reverseMap.put(25,25);
    }
    public static void main(String[] args) {
    
    
        encrypt("hot",7,3);
        decrypt("AXG",7,3);
    }

    /**
     * (ax+b)mod26 是加密函数
     * @param resource
     * @param a
     * @param b
     */
    public static void encrypt(String resource,int a,int b){
    
    
        if(!reverseMap.containsKey(a)|| b<0||b>26){
    
    
            throw new RuntimeException("参数有误,请重新输入");
        }
     char[] arr = resource.toUpperCase().toCharArray();
     StringBuilder result = new StringBuilder();
     for(int i=0;i<arr.length;i++){
    
    
       int temp =  (a*(arr[i]-'A')+b)%26<0?(a*(arr[i]-'A')+b)%26+26:(a*(arr[i]-'A')+b)%26;
         result.append((char)(temp+'A'));
     }
        System.out.println(result);
    }

    /**
     * 解密函数为a逆(y-b)mod26
     * @param resource
     * @param a
     * @param b
     */
    public static void decrypt(String resource,int a,int b){
    
    
        int  re =reverseMap.get(a);//求得逆 后续会整理求逆的方法
        char[] arr = resource.toUpperCase().toCharArray();
        StringBuilder result = new StringBuilder();
        for(int i=0;i<arr.length;i++){
    
    
            int temp = (re*(arr[i]-'A'-b))%26<0?(re*(arr[i]-'A'-b))%26+26:(re*(arr[i]-'A'-b))%26;
            result.append((char)(temp+'A'));
        }
        System.out.println(result);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_51656605/article/details/110388691