ZUC加密算法实现-软件版本Java

ZUC加密算法实现

参考资料

https://max.book118.com/html/2017/0716/122521494.shtm

一.运行结果展示

ZUC加密算法实现-软件版本Java_第1张图片

ZUC加密算法实现-软件版本Java_第2张图片

二. 程序源码


import java.util.*;
// import java.lang.*;

public class zuc {
    public static void main(String[] args) {
        Scanner S = new Scanner(System.in);
        System.out.println("请输入十六进制128位明文:");
        // String ming = S.next();
        String ming = "00000000000000000000000000000000";
        // 84319aa8de6915ca1f6bda6bfbd8c766
        System.out.println("请输入十六进制128位密钥:");
        // String k = S.next();
        String k = "00000000000000000000000000000000";
        // 3d4c4be96a82fdaeb58f641db17b455b
        S.close();
        int[] mingwen = Algorithm.DataFormat(ming);// 16
        int[] key = Algorithm.DataFormat(k);// 16
        int[] s = Algorithm.keyInstall(key, mingwen);// 密钥装入
        System.out.println("\n明文:");
        for (int i = 0; i < mingwen.length; i++) {
            System.out.printf("%x ", mingwen[i]);
        }
        System.out.println("\n密钥:");
        for (int i = 0; i < mingwen.length; i++) {
            System.out.printf("%x ", key[i]);
        }
        System.out.println("\ns:");
        for (int i = 0; i < s.length; i++) {
            System.out.printf("%x ", s[i]);
        }
        int[] x = Algorithm.bitReconstruction(s);
        int r1 = 0, r2 = 0;
        int[] Wrr = Algorithm.F(x, r1, r2);

        s = Algorithm.LFSRInitialisation(s, Wrr[0]);
        r1 = Wrr[1];
        r2 = Wrr[2];

        System.out.println("\n初始化后的x,r,w,s15\n");
        for (int i = 0; i < x.length; i++) {
            System.out.printf("%x ", x[i]);
        }
        System.out.printf("%x ", r1);
        System.out.printf("%x ", r2);
        System.out.printf("%x ", Wrr[0]);
        System.out.printf("%x ", s[15]);

        // System.out.println("\n第一次线性移位后的s:\n");
        // for (int i = 0; i < s.length; i++) {
        // System.out.printf("%x ", s[i]);
        // }

        for (int i = 0; i < 31; i++) {// 初始化模式
            x = Algorithm.bitReconstruction(s);
            Wrr = Algorithm.F(x, r1, r2);
            s = Algorithm.LFSRInitialisation(s, Wrr[0]);
            r1 = Wrr[1];
            r2 = Wrr[2];
            // System.out.printf("\n第%d次线性移位后的s:", i);
            // for (int ii = 0; ii < s.length; ii++) {
            // System.out.printf("%x ", s[ii]);
            // }
            // System.out.printf("\n第%d次后的x,r,w,s15\n", i);
            // for (int ii = 0; ii < x.length; ii++) {
            // System.out.printf("%x ", x[ii]);
            // }
            // System.out.printf("%x ", r1);
            // System.out.printf("%x ", r2);
            // System.out.printf("%x ", Wrr[0]);
            // System.out.printf("%x ", s[15]);

        }
        System.out.println("\n初始化后的s:");
        for (int ii = 0; ii < s.length; ii++) {
            System.out.printf("%x ", s[ii]);
        }
        System.out.println("\n初始化后的x,r,w,s15\n");
        for (int ii = 0; ii < x.length; ii++) {
            System.out.printf("%x ", x[ii]);
        }
        System.out.printf("%x ", r1);
        System.out.printf("%x ", r2);
        System.out.printf("%x ", Wrr[0]);
        System.out.printf("%x ", s[15]);
        // 工作模式//第一次舍弃W
        int z = 0;
        x = Algorithm.bitReconstruction(s);
        Wrr = Algorithm.F(x, r1, r2);
        s = Algorithm.LFSRWorking(s);
        r1 = Wrr[1];
        r2 = Wrr[2];
        // 不舍弃
        x = Algorithm.bitReconstruction(s);
        Wrr = Algorithm.F(x, r1, r2);
        z = Wrr[0] ^ x[3];
        s = Algorithm.LFSRWorking(s);
        r1 = Wrr[1];
        r2 = Wrr[2];
        System.out.printf("运行后:\nz1:%x ", z);
        // 不舍弃第二次运行
        x = Algorithm.bitReconstruction(s);
        Wrr = Algorithm.F(x, r1, r2);
        z = Wrr[0] ^ x[3];
        s = Algorithm.LFSRWorking(s);
        r1 = Wrr[1];
        r2 = Wrr[2];
        System.out.printf("第二次运行后:\nz2:%x ", z);

        // int[] x = Algorithm.bitReconstruction(S);
        // System.out.println("\n比特重组:");
        // for (int i = 0; i < x.length; i++) {
        // System.out.printf("%x ", x[i]);
        // }

    }
}

// 84319aa8de6915ca1f6bda6bfbd8c766
// 3d4c4be96a82fdaeb58f641db17b455b
class Algorithm {
    static int[] DataFormat(String s) {// 数据格式转换,将十六进制字符串转换为数据表输出
        int[] a = new int[16];
        for (int i = 0; i < 16; i++) {
            a[i] = Integer.parseInt(s.substring(2 * i, 2 * i + 2), 16);
        }
        return a;
    }

    static int[] keyInstall(int[] k, int[] iv) {
        int[] d = new int[16];
        d[0] = Integer.parseInt("100010011010111", 2);
        d[1] = Integer.parseInt("010011010111100", 2);
        d[2] = Integer.parseInt("110001001101011", 2);
        d[3] = Integer.parseInt("001001101011110", 2);
        d[4] = Integer.parseInt("101011110001001", 2);
        d[5] = Integer.parseInt("011010111100010", 2);
        d[6] = Integer.parseInt("111000100110101", 2);
        d[7] = Integer.parseInt("000100110101111", 2);
        d[8] = Integer.parseInt("100110101111000", 2);
        d[9] = Integer.parseInt("010111100010011", 2);
        d[10] = Integer.parseInt("110101111000100", 2);
        d[11] = Integer.parseInt("001101011110001", 2);
        d[12] = Integer.parseInt("101111000100110", 2);
        d[13] = Integer.parseInt("011110001001101", 2);
        d[14] = Integer.parseInt("111100010011010", 2);
        d[15] = Integer.parseInt("100011110101100", 2);
        // System.out.println("d:");
        // for (int i = 0; i < d.length; i++) {
        // System.out.printf("%x ", d[i]);
        // }
        int[] s = new int[16];
        for (int i = 0; i < 16; i++) {
            s[i] = k[i] << 23 ^ d[i] << 8 ^ iv[i];
        }
        return s;
    }

    static int[] bitReconstruction(int[] s) {
        int[] x = new int[4];
        x[0] = ((s[15] & 0x7FFF8000) << 1) | (s[14] & 0x0000ffff);
        x[1] = ((s[11] & 0x0000ffff) << 16) | ((s[9]) >>> 15);
        x[2] = ((s[7] & 0x0000ffff) << 16) | ((s[5]) >>> 15);
        x[3] = ((s[2] & 0x0000ffff) << 16) | ((s[0]) >>> 15);
        return x;
    }

    static int[] F(int[] x, int r1, int r2) {
        int w, w1, w2;
        w = ((x[0] ^ r1) + r2) & 0xffffffff;
        w1 = (r1 + x[1]) & 0xffffffff;
        w2 = r2 ^ x[2];
        int[] ans = new int[3];
        ans[0] = w;
        ans[1] = Algorithm.s(Algorithm.L1(((w1 & 0x0000ffff) << 16) ^ (w2 >>> 16)));
        ans[2] = Algorithm.s(Algorithm.L2(((w2 & 0x0000ffff) << 16) ^ (w1 >>> 16)));
        return ans;
    }

    static int L1(int in) {
        return in ^ (in << 2 ^ in >>> 30) ^ (in << 10 ^ in >>> 22) ^ (in << 18 ^ in >>> 14) ^ (in << 24 ^ in >>> 8);
    }

    static int L2(int in) {
        return in ^ (in << 8 ^ in >>> 24) ^ (in << 14 ^ in >>> 18) ^ (in << 22 ^ in >>> 10) ^ (in << 30 ^ in >>> 2);
    }

    static int s(int in) {
        int[] S0 = { 0x3e, 0x72, 0x5b, 0x47, 0xca, 0xe0, 0x00, 0x33, 0x04, 0xd1, 0x54, 0x98, 0x09, 0xb9, 0x6d, 0xcb,
                0x7b, 0x1b, 0xf9, 0x32, 0xaf, 0x9d, 0x6a, 0xa5, 0xb8, 0x2d, 0xfc, 0x1d, 0x08, 0x53, 0x03, 0x90, 0x4d,
                0x4e, 0x84, 0x99, 0xe4, 0xce, 0xd9, 0x91, 0xdd, 0xb6, 0x85, 0x48, 0x8b, 0x29, 0x6e, 0xac, 0xcd, 0xc1,
                0xf8, 0x1e, 0x73, 0x43, 0x69, 0xc6, 0xb5, 0xbd, 0xfd, 0x39, 0x63, 0x20, 0xd4, 0x38, 0x76, 0x7d, 0xb2,
                0xa7, 0xcf, 0xed, 0x57, 0xc5, 0xf3, 0x2c, 0xbb, 0x14, 0x21, 0x06, 0x55, 0x9b, 0xe3, 0xef, 0x5e, 0x31,
                0x4f, 0x7f, 0x5a, 0xa4, 0x0d, 0x82, 0x51, 0x49, 0x5f, 0xba, 0x58, 0x1c, 0x4a, 0x16, 0xd5, 0x17, 0xa8,
                0x92, 0x24, 0x1f, 0x8c, 0xff, 0xd8, 0xae, 0x2e, 0x01, 0xd3, 0xad, 0x3b, 0x4b, 0xda, 0x46, 0xeb, 0xc9,
                0xde, 0x9a, 0x8f, 0x87, 0xd7, 0x3a, 0x80, 0x6f, 0x2f, 0xc8, 0xb1, 0xb4, 0x37, 0xf7, 0x0a, 0x22, 0x13,
                0x28, 0x7c, 0xcc, 0x3c, 0x89, 0xc7, 0xc3, 0x96, 0x56, 0x07, 0xbf, 0x7e, 0xf0, 0x0b, 0x2b, 0x97, 0x52,
                0x35, 0x41, 0x79, 0x61, 0xa6, 0x4c, 0x10, 0xfe, 0xbc, 0x26, 0x95, 0x88, 0x8a, 0xb0, 0xa3, 0xfb, 0xc0,
                0x18, 0x94, 0xf2, 0xe1, 0xe5, 0xe9, 0x5d, 0xd0, 0xdc, 0x11, 0x66, 0x64, 0x5c, 0xec, 0x59, 0x42, 0x75,
                0x12, 0xf5, 0x74, 0x9c, 0xaa, 0x23, 0x0e, 0x86, 0xab, 0xbe, 0x2a, 0x02, 0xe7, 0x67, 0xe6, 0x44, 0xa2,
                0x6c, 0xc2, 0x93, 0x9f, 0xf1, 0xf6, 0xfa, 0x36, 0xd2, 0x50, 0x68, 0x9e, 0x62, 0x71, 0x15, 0x3d, 0xd6,
                0x40, 0xc4, 0xe2, 0x0f, 0x8e, 0x83, 0x77, 0x6b, 0x25, 0x05, 0x3f, 0x0c, 0x30, 0xea, 0x70, 0xb7, 0xa1,
                0xe8, 0xa9, 0x65, 0x8d, 0x27, 0x1a, 0xdb, 0x81, 0xb3, 0xa0, 0xf4, 0x45, 0x7a, 0x19, 0xdf, 0xee, 0x78,
                0x34, 0x60 };
        int[] S1 = { 0x55, 0xc2, 0x63, 0x71, 0x3b, 0xc8, 0x47, 0x86, 0x9f, 0x3c, 0xda, 0x5b, 0x29, 0xaa, 0xfd, 0x77,
                0x8c, 0xc5, 0x94, 0x0c, 0xa6, 0x1a, 0x13, 0x00, 0xe3, 0xa8, 0x16, 0x72, 0x40, 0xf9, 0xf8, 0x42, 0x44,
                0x26, 0x68, 0x96, 0x81, 0xd9, 0x45, 0x3e, 0x10, 0x76, 0xc6, 0xa7, 0x8b, 0x39, 0x43, 0xe1, 0x3a, 0xb5,
                0x56, 0x2a, 0xc0, 0x6d, 0xb3, 0x05, 0x22, 0x66, 0xbf, 0xdc, 0x0b, 0xfa, 0x62, 0x48, 0xdd, 0x20, 0x11,
                0x06, 0x36, 0xc9, 0xc1, 0xcf, 0xf6, 0x27, 0x52, 0xbb, 0x69, 0xf5, 0xd4, 0x87, 0x7f, 0x84, 0x4c, 0xd2,
                0x9c, 0x57, 0xa4, 0xbc, 0x4f, 0x9a, 0xdf, 0xfe, 0xd6, 0x8d, 0x7a, 0xeb, 0x2b, 0x53, 0xd8, 0x5c, 0xa1,
                0x14, 0x17, 0xfb, 0x23, 0xd5, 0x7d, 0x30, 0x67, 0x73, 0x08, 0x09, 0xee, 0xb7, 0x70, 0x3f, 0x61, 0xb2,
                0x19, 0x8e, 0x4e, 0xe5, 0x4b, 0x93, 0x8f, 0x5d, 0xdb, 0xa9, 0xad, 0xf1, 0xae, 0x2e, 0xcb, 0x0d, 0xfc,
                0xf4, 0x2d, 0x46, 0x6e, 0x1d, 0x97, 0xe8, 0xd1, 0xe9, 0x4d, 0x37, 0xa5, 0x75, 0x5e, 0x83, 0x9e, 0xab,
                0x82, 0x9d, 0xb9, 0x1c, 0xe0, 0xcd, 0x49, 0x89, 0x01, 0xb6, 0xbd, 0x58, 0x24, 0xa2, 0x5f, 0x38, 0x78,
                0x99, 0x15, 0x90, 0x50, 0xb8, 0x95, 0xe4, 0xd0, 0x91, 0xc7, 0xce, 0xed, 0x0f, 0xb4, 0x6f, 0xa0, 0xcc,
                0xf0, 0x02, 0x4a, 0x79, 0xc3, 0xde, 0xa3, 0xef, 0xea, 0x51, 0xe6, 0x6b, 0x18, 0xec, 0x1b, 0x2c, 0x80,
                0xf7, 0x74, 0xe7, 0xff, 0x21, 0x5a, 0x6a, 0x54, 0x1e, 0x41, 0x31, 0x92, 0x35, 0xc4, 0x33, 0x07, 0x0a,
                0xba, 0x7e, 0x0e, 0x34, 0x88, 0xb1, 0x98, 0x7c, 0xf3, 0x3d, 0x60, 0x6c, 0x7b, 0xca, 0xd3, 0x1f, 0x32,
                0x65, 0x04, 0x28, 0x64, 0xbe, 0x85, 0x9b, 0x2f, 0x59, 0x8a, 0xd7, 0xb0, 0x25, 0xac, 0xaf, 0x12, 0x03,
                0xe2, 0xf2 };
        int[] x = new int[4];
        x[0] = (in & 0xff000000) >> 24;
        x[1] = (in & 0x00ff0000) >> 16;
        x[2] = (in & 0x0000ff00) >> 8;
        x[3] = (in & 0x000000ff);
        int[] y = new int[4];
        y[0] = S0[((x[0] & 0xf0) >> 4) * 16 + (x[0] & 0x0f)];
        y[1] = S1[((x[1] & 0xf0) >> 4) * 16 + (x[1] & 0x0f)];
        y[2] = S0[((x[2] & 0xf0) >> 4) * 16 + (x[2] & 0x0f)];
        y[3] = S1[((x[3] & 0xf0) >> 4) * 16 + (x[3] & 0x0f)];
        return (y[0] << 24) ^ (y[1] << 16) ^ (y[2] << 8) ^ (y[3]);
    }

    static int[] LFSRInitialisation(int[] s, int w) {
        int f = s[0];
        int v = Algorithm.mulInModule(8, s[0]);
        f = Algorithm.addInModule(f, v);
        v = Algorithm.mulInModule(20, s[4]);
        f = Algorithm.addInModule(f, v);
        v = Algorithm.mulInModule(21, s[10]);
        f = Algorithm.addInModule(f, v);
        v = Algorithm.mulInModule(17, s[13]);
        f = Algorithm.addInModule(f, v);
        v = Algorithm.mulInModule(15, s[15]);
        f = Algorithm.addInModule(f, v);

        int[] rets = new int[16];
        f = Algorithm.addInModule(f, w >>> 1);
        if (f == 0) {
            f = 0x7fffffff;
        }
        for (int i = 0; i < 15; i++) {
            rets[i] = s[i + 1];
        }
        rets[15] = f;

        return rets;
    }

    static int[] LFSRWorking(int[] s) {
        int f = s[0];
        int v = Algorithm.mulInModule(8, s[0]);
        f = Algorithm.addInModule(f, v);
        v = Algorithm.mulInModule(20, s[4]);
        f = Algorithm.addInModule(f, v);
        v = Algorithm.mulInModule(21, s[10]);
        f = Algorithm.addInModule(f, v);
        v = Algorithm.mulInModule(17, s[13]);
        f = Algorithm.addInModule(f, v);
        v = Algorithm.mulInModule(15, s[15]);
        f = Algorithm.addInModule(f, v);

        int[] rets = new int[16];
        if (f == 0) {
            f = 0x7fffffff;
        }
        for (int i = 0; i < 15; i++) {
            rets[i] = s[i + 1];
        }
        rets[15] = f;
        return rets;
    }

    static int addInModule(int a, int b) {
        int c = a + b;
        return (c & 0x7fffffff) + (c >>> 31);
    }

    static int mulInModule(int a, int b) {// a是常量的那个

        return ((b << a) | (b >>> (31 - a))) & 0x7fffffff;
    }

}
// 3CA10B2157F01916902E1380ACC107BD

三.写在最后

如果想要修改测试向量, 可以在main函数中开头有相关语句, 我目前使用的是常量模式. 如果想修改成从
终端输入, 可以将常量语句换成后面被注释的语句. 具体详看代码肯定能看懂.
如果想看中间结果, 代码中的很多用于输出的注释取消掉即可, 每步的中间结果都有, 此代码系我调试完成
后注释掉的.

你可能感兴趣的:(密码学,java)