【密码学-凯撒密码】

凯撒密码原理

凯撒密码的加密代换和解密代换分别为
c = E k ( m ) = m + 3 ( m o d 26 ) c=E_{k}(m)=m + 3(mod 26) c=Ek(m)=m+3(mod26) 0 < = m < = 25 0<= m <= 25 0<=m<=25
m = D k ( c ) = c − 3 ( m o d 26 ) m=D_{k}(c)=c - 3(mod 26) m=Dk(c)=c3(mod26) 0 < = c < = 25 0<=c<=25 0<=c<=25
其中,3是加解密使用的密钥,即 k = 3 k=3 k=3,加密时,每个字母向后移3位(循环移位,字母 x x x移到 a a a y y y移到 b b b z z z移到 c c c)。解密时,每个字母向前移3位(循环移位)

移位变换

移位变换的加解密分别是
c = E k ( m ) = m + k ( m o d 26 ) c=E_{k}(m)=m+k(mod 26) c=Ek(m)=m+k(mod26) 0 < = m , k < = 25 0<=m,k<=25 0<=m,k<=25
m = D k ( c ) = c − k ( m o d 26 ) m=D_{k}(c)=c - k(mod 26) m=Dk(c)=ck(mod26) 0 < = c , k < = 25 0<=c,k<=25 0<=c,k<=25

仿射变换

仿射变换的加解密分别是
c = E a , b ( m ) = a m + b ( m o d 26 ) c=E_{a,b}(m)=am+b(mod 26) c=Ea,b(m)=am+b(mod26)
m = D a , b ( c ) = a − 1 ( c − b ) ( m o d 26 ) m=D_{a,b}(c)=a^{-1}(c-b)(mod 26) m=Da,b(c)=a1(cb)(mod26)
其中, a , b a,b a,b是密钥,为满足 0 < = a , b < = 25 0<=a,b<=25 0<=a,b<=25 g c d ( a , 26 ) = 1 gcd(a,26)=1 gcd(a,26)=1的整数,其中 g c d ( a , 26 ) gcd(a,26) gcd(a,26)表示 a , 26 a,26 a,26的最大公因子, g c d ( a , 26 ) = 1 gcd(a,26)=1 gcd(a,26)=1表示 a a a 26 26 26是互素的, a − 1 a^{-1} a1表示 a a a的逆元,即 a − 1 ∗ a = 1 m o d 26 a^{-1}*a=1mod 26 a1a=1mod26

代码实现-凯撒密码

package com.cqu;

public class KaiSaEncryptionTest {
    public static void main(String args[]) {
        String input = "Hello World";
        Integer key = 3;
        String c1 = encryptionByKasStra(input);
        System.out.println(c1);
        String p1 = decryptByKasStra(c1);
        System.out.println("解密后的明文为: " + p1);
    }

    /**
     * 凯撒加密
     */
    private static String encryptionByKasStra(String input) {
        char[] inputArray = input.toCharArray();
        StringBuilder cipherText = new StringBuilder();
        for (char ia : inputArray) {
            int b = ia;
            b = (b + 3);
            char newb = (char) b;
            cipherText.append(newb);
        }
        return cipherText.toString();
    }

    /**
     * 凯撒解密
     */
    private static String decryptByKasStra(String cipherText) {
        char[] cipherArray = cipherText.toCharArray();
        StringBuilder plainText = new StringBuilder();
        for (char ca : cipherArray) {
            int m = ca;
            m = m - 3;
            char newm = (char) m;
            plainText.append(newm);
        }
        return plainText.toString();
    }
}

代码实现-放射变换

package com.cqu;

import com.cqu.enums.EnglishCodeNumberMap;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author wuyanling
 */
public class KaiSaEncryptionTest {

    public static void main(String args[]) {
        String input1 = "security";
        String input2 = "vlxijh";
        Integer a = 7;
        Integer b = 21;

        String c1 = encryptionByKasStra(a, b, input1);
        System.out.println("加密后的秘文为:" + c1);
//        String c1 = encryptionByKasStra(input);
//        System.out.println(c1);
        String p1 = decryptByKasStra(a, b, input2);
        System.out.println("解密后的明文为: " + p1);

        //System.out.println(15*(-4) % 26);
//        System.out.println(EnglishCodeNumberMap.getNumByCode("b"));
    }

    /**
     * 凯撒加密
     */
    private static String encryptionByKasStra(Integer a, Integer b, String input) {
        if (Objects.isNull(input)) {
            return "";
        }
        char[] inputArray = input.toCharArray();
        List<Integer> numberArray = Arrays.asList();

        //这一步是解决抛java.lang.UnsupportedOperationException异常
        List plainArray = new ArrayList(numberArray);

        for (char ia : inputArray) {
            for (EnglishCodeNumberMap map : EnglishCodeNumberMap.values()) {
                if(map.getCode().equals(String.valueOf(ia))) {
                    plainArray.add(EnglishCodeNumberMap.getNumByCode(String.valueOf(ia)));
                    continue;
                }

            }
        }
        StringBuilder cipherText = new StringBuilder();
        List<Integer> cipherArray = (List<Integer>) plainArray.stream().map(e -> (a*(int) e + b) % 26).collect(Collectors.toList());
        for (Integer ci : cipherArray) {
            for (EnglishCodeNumberMap map : EnglishCodeNumberMap.values()) {
                if (map.getNum().equals(ci)) {
                    cipherText.append(map.getCode());
                    continue;
                }
            }

        }
        return cipherText.toString();
    }

    /**
     * 凯撒解密
     */
    private static String decryptByKasStra(Integer a, Integer b, String cipherText) {
        if (Objects.isNull(cipherText)) {
            return "";
        }
        char[] cipherArray = cipherText.toCharArray();
        List<Integer> numberArray = Arrays.asList();
        List ciphnerArray = new ArrayList(numberArray);
        for (char ia : cipherArray) {
            for (EnglishCodeNumberMap map : EnglishCodeNumberMap.values()) {
                if(map.getCode().equals(String.valueOf(ia))) {
                    ciphnerArray.add(EnglishCodeNumberMap.getNumByCode(String.valueOf(ia)));
                    continue;
                }

            }
        }
        StringBuilder plainText = new StringBuilder();
        Integer c = getInverseElement(a);
        List<Integer> plainArray = (List<Integer>) ciphnerArray.stream().map(e ->{
            if ((int) e - b > 0) {
                return c * ((int) e - b) % 26;
            }else{
                //同余 如果 a mod b中a<0,则将(a+b) mod b
                return c * ((int) e - b + 26) % 26;
            }
        }).collect(Collectors.toList());
        for (Integer pa : plainArray) {
           for (EnglishCodeNumberMap map : EnglishCodeNumberMap.values()) {
               if (map.getNum().equals(pa)) {
                   plainText.append(map.getCode());
                   continue;
               }
           }
        }
        return plainText.toString();
    }

    private static Integer getInverseElement(Integer a) {
        if (Objects.isNull(a)) {
            return null;
        }
        Integer c = null;
        for (int i = 0; i < 26; i ++) {
            if (a*i % 26 == 1) {
                c = i;
                break;
            }
        }
        return c;
    }
}

其中字母与数字映射枚举如下

package com.cqu.enums;




import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author wuyanling
 */

public enum EnglishCodeNumberMap {
    a("a", 0),
    b("b", 1),
    c("c", 2),
    d("d", 3),
    e("e", 4),
    f("f", 5),
    g("g", 6),
    h("h", 7),
    i("i", 8),
    j("j", 9),
    k("k", 10),
    l("l", 11),
    m("m", 12),
    n("n", 13),
    o("o", 14),
    p("p", 15),
    q("q", 16),
    r("r", 17),
    s("s", 18),
    t("t", 19),
    u("u", 20),
    v("v", 21),
    w("w", 22),
    x("x", 23),
    y("y", 24),
    z("z", 25),
    ;
    private String code;
    private Integer num;

    EnglishCodeNumberMap(String code, Integer num) {
        this.code = code;
        this.num = num;
    }

    public  String getCode() {
        return code;
    }

    public Integer getNum() {
        return num;
    }
    private static Map<String, EnglishCodeNumberMap> codeMap =  new HashMap<>();
    static {
        Arrays.stream(EnglishCodeNumberMap.values()).forEach(e -> codeMap.put(e.code, e));
    }


    public static EnglishCodeNumberMap ofType(String code) {
        if (Objects.isNull(code)) {
            return null;
        }

        return codeMap.get(code);
    }

    public static Integer getNumByCode(String code) {
        EnglishCodeNumberMap te = ofType(code);
        if (Objects.isNull(te)) {
            return -1;
        }

        return te.num;
    }
    @Override
    public String toString() {
        return name()+":"+ code;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值