【现代密码学】实验一 祖冲之密码算法

本人一直想找时间系统整理一下之前做过的一些实验,便于后续用到的时候可以尽快的使用,po出来也便于大家交流学习,有问题欢迎交流指正,与诸君共勉!

实验目的

(1)了解祖冲之密码算法的线性反馈移位寄存器;

(2)了解祖冲之密码算法的非线性函数;

(3)熟悉祖冲之密码算法的工作流程。

实验原理

图1 祖冲之密码算法结构图

祖冲之算法结构从逻辑上分为上中下三层, 如图1所示。上层16线性反馈移位寄存器(LFSR), 层是比特重组(Bit Recondtruction,BR), 层是非线性函数F

下面是各层的具体解释。

1.线性反馈移位寄存器

线性反馈移位寄存器(LFSR)由16个31比特寄存器单元组成,每个单元在集合

中取值。

线性反馈移位寄存器的特征多项式是有限域GF()上的16次本原多项式

因此,其输出为有限域GF)上的m序列,具有良好的随机性。

线性反馈移位寄存器的工作模式有两种:初始化模式和工作模式。

(1)初始化模式

在初始化模式中,LFSR在接收一个31比特字u,u是由非线性函数F的32比特输出W通过舍弃最低位比特得到,即u=W>>1。计算过程如下:

LFSRWithInitialisationMode(u)

{

  1. ;
  2.  ;
  3. 如果 ,则置 
  4.  

}

(2)工作模式

在工作模式下,LFSR没有输入。计算过程如下:

LFSRWithWorkMode()

{

  1.  ;
  2. 如果 ,则置 
  3.  

}

比较两种模式,差别在于初始化时需要引入非线性函数F输出的W通过舍弃最低位比特得到u,而工作模式不需要。目的在于,引入非线性函数F的输出,使线性反馈移位寄存器的状态随机化。

LFSR的作用主要是为中层的比特重组(BR)提供随机性良好的输入驱动。

2.比特重组

比特重组从LFSR的寄存器单元中抽取128比特组成4个32比特字 ,其中前3个字将用于下层的非线性函数F,第四个字参与密钥流的计算。

具体计算过程如下:

BitReconstruction()

{

  1.  ;
  2.  ;
  3.  ;
  4.  ;

}

注意:对每个i(0i15), 的比特长是31,所以 的第30到第15比特位构成,而不是第31到第16比特位。

3.非线性函数F

非线性函数F有2个32比特长的存储单元R1R2,其输入为来自上层比特重组的3个32比特字X0,X1,X2,输出为一个32比特字W。因此,非线性函数F是一个把96比特压缩到32比特的一个非线性函数。具体计算过程如下:

F()

{

  1. ;
  2. ;
  3. ;
  4. ;
  5. ;

}

其中,S是32×32的S盒,L1L2是线性变换。S盒及的描述如下:

(1)S盒。32×32(即输入长和输出长都是32比特)的S盒S由4个并置的8×8的S盒构成,即

其中,,于是有

的定义表省略。

设x是(或)的8比特长输入,将x写成两个十六进制数x=h| l,那么 (或 )的输出是S盒状态 (或 )表的第h行l列交叉位置的十六进制数。

设S的输入、输出分别为X(32比特长)和Y(32比特长),将X和Y分别表示成4个字节 , ,那么 ,(i=0,1,2,3)。

(2)线性变换   为32比特线性变换,定义如下:

 

 

其中,符号a<<<n表示把a循环左移n位。

易知其中线性变换 与SM4密码中的线性变换L(B)相同。

在非线性函数F中采用非线性变换S盒的目的是提供混淆作用,采用线性变换L的目的是提供扩散作用。正是混淆和扩散相互配合提高了密码的安全性。

非线性函数F输出的W与比特重组(BR)输出的 异或,形成输出密钥序列Z。

4.密钥装载

密钥装载过程将128比特的初始密钥k和128比特的初始向量IV扩展为16个31比特长的整数,作为LFSR寄存器单元 的初始状态。

设k和IV分别为

 

 

其中,  均为8比特长字节,0i15。密钥装入过程如下:

(1)设D为240比特的常量,可按如下方式分成16个15比特的子串:

 

其中, 的二进制表示为:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(2)对0i15,取 

实验内容及步骤

实验基本方法

用java语言编写祖冲之密码算法,输出加解密结果。

实验步骤

(1)祖冲之密码算法的输入输出;

(2)祖冲之密码算法的初始化;

(3)祖冲之密码算法的密钥流产生;

(4)祖冲之密码算法的加解密。

祖冲之密码的运行

算法的运行有两个阶段:初始化阶段和工作阶段。

  • 初始化阶段

调用密钥装载过程,将128比特的初始密钥k和128比特的初始向量IV装入LFSR的寄存器单元变量s0,s1,...,s14,s15中,作为LFSR的初态,并置非线性函数F中的32比特存储单元R1和R2全为0.

然后重复执行以下过程32次:

  1. BitReconstruction();
  2. W=F(X0,X1,X2);
  3. LFSRWithInitialisationMode(u)。       
  • 工作阶段

初始化阶段之后,执行工作阶段。

首先执行以下过程一次,并将F的输出W丢弃:

  1. BitReconstruction();
  2. W=F( 

(3)  LFSRWithWorkMode(u)。

然后进入密钥输出阶段,其中每进行一次循环,执行以下过程一次,输出一个32比特的密钥字Z:

  1. BitConstruction():
  2. Z= F( ;

     3.LFSRWithWorkMode()。

实验代码

package main.java;
import java.util.Scanner;
 
/**
 * ZUC加解密系统用户交互主类
 * @author AGATHA_66
 * @date 2022年11月10日
 * @todo
 */
public class ZUC_main {
	/**
	 * 初始化操作之后功能选择菜单
	 */
	public static void menu(){
		 System.out.println("|=============请选择您的操作:=============|");
		 System.out.println("|           1.产生密钥流                                               |");
		 System.out.println("|           2.加密                                                          |");
		 System.out.println("|           3.解密                                                          |");
		 System.out.println("|           4.退出                                                          |");
		 System.out.println("|=====================================|");
	}
	
	/**
	 * ZUC初始化用户交互过程
	 * @return 返回初始化后的ZUC对象
	 */
	public static ZUC ini_main() {
		Scanner reader = new Scanner(System.in);
		int[] iv = new int[16];
		int[] key = new int[16];
		System.out.println("请输入初始密钥KEY:--------------------");
		for(int i = 0; i < 16;i++)
		iv[i] = reader.nextInt();
		System.out.println("请输入初始向量IV:--------------------");
		for(int i = 0; i < 16;i++)
		key[i] = reader.nextInt();
		ZUC zuc = new ZUC();
		//调用初始化函数
	    zuc.Initialization(key, iv);
	    return zuc;
	}
	
	public static void creat_KeyStream_main() {
		Scanner reader = new Scanner(System.in);
		System.out.println("请输入LENGTH:--------------");
		 int keyStreamSize = reader.nextInt();
		 long[] pKeyStream = new long[keyStreamSize];
	     ZUC.GenerateKeyStream(pKeyStream, keyStreamSize);
	     System.out.println("--------------------------");
	    	System.out.println("生成密钥流:");
	    	for (int i = 0; i < keyStreamSize; ++i) {
	    		//System.out.print("第"+(i+1)+"个:");
	         	System.out.print(Integer.toHexString((int)pKeyStream[i])+" ");
	         }
	    System.out.println();
	}
	
	/**
	 * 解密过程将接收到的16进制或10进制的密文转换为long数组 用户交互过程
	 * @return
	 */
	public static long[] getC(int keyStreamSize) {
		Scanner reader = new Scanner(System.in);
		System.out.println("-请选择密文进制数:(1)10进制;(2)16进制");
		int choice2 = reader.nextInt();
		System.out.println("请输入密文:");
		long[] C = new long[keyStreamSize];
		if(choice2==1) {//密文为10进制表示
            for(int i = 0;i < keyStreamSize;i++)
        	    C[i] = reader.nextLong();
        }
		else if(choice2==2) {//密文为16进制表示
			String[] C0 = new String[keyStreamSize];
            for(int i = 0;i < keyStreamSize;i++) {
            	C0[i] = reader.next();
            	C[i] = Long.parseLong(C0[i],16);//16进制转10进制
            }
        }
		return C;
	}
	
	/**
	 * 主函数
	 * @param args
	 */
	public static void main(String[] args) {
		
		boolean fig = true;
		Scanner reader = new Scanner(System.in);
		
			//初始化
			ZUC zuc = ini_main();
			System.out.println("ZUC初始化成功!");
	        menu();
			int choice = reader.nextInt();
			int choice0 = 0;
				//防止输入不规范bug
				if(choice == 1)choice0 = 1;
				else if(choice == 2)choice0 = 2;
				else if(choice == 3)choice0 = 3;
				else if(choice == 4)choice0 = 4;
				else System.out.println("请输入1~4的数字!");
			switch (choice0){
			case 1://选择产生密钥流
				creat_KeyStream_main();
			    break;//产生密钥流
			case 2://选择加密
				//明文输入
		        System.out.println("请输入明文:--------------------");
		        String M = reader.next();
		        //产生密钥流(定长)
		        int keyStreamSize = M.length();
		        long[] pKeyStream = new long[keyStreamSize];
		        ZUC.GenerateKeyStream(pKeyStream, keyStreamSize);
		        //加密:
		        long[] C = zuc.Encry(M,pKeyStream);
		        
		        char[] M2 = zuc.Decry(C,pKeyStream);
		        System.out.println();
				break;
			case 3://选择解密
				//密文输入
				System.out.println("请输入比特流比特长度LENGTH:");
				int keyStreamSize1 = reader.nextInt();
				long[] pKeyStream1 = new long[keyStreamSize1];
		        ZUC.GenerateKeyStream(pKeyStream1, keyStreamSize1);
		        long[] C1 = getC(keyStreamSize1);
		       
				//解密:
		        char[] mm = zuc.Decry(C1,pKeyStream1);
		        System.out.println();
		        break;
			case 4://系统退出
					System.out.println("系统已退出!");return;
			default:
					break;
		    }
			
			reader.nextLine();//吸收回车符
			System.out.println("按回车键退出");
			reader.nextLine();
			reader.close();
			System.exit(0);
		 
    }
}



package main.java;
 
/**
 * @author AGATHA
 * @date 2022年11月8日
 * @todo 祖冲之密码算法加密工具类
 */
public class ZUC {
    /** 线性反馈移位寄存器状态 数组*/
    private static int[] LFSR_S = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    /** F 寄存器 */
    private static int F_R1 = 0;
    private static int F_R2 = 0;
    /** 比特重组输出数组 */
    private static int[] BRC_X = {0,0,0,0};
    /**S盒 */
    private static 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
    };
    /** S盒 */
    private static 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
    };
 
    /** 240比特常量D  16*15*/
    private static int[] EK_d = {
            0x44D7, 0x26BC, 0x626B, 0x135E, 0x5789, 0x35E2, 0x7135, 0x09AF,
            0x4D78, 0x2F13, 0x6BC4, 0x1AF1, 0x5E26, 0x3C4D, 0x789A, 0x47AC
    };
 
    /**
     * 模加     c = a + b mod 2^31 - 1  
     * (两个数的和 和 7FFFFFFF按位与 )+(两个数的和 和 80000000按位与的结果 无符号右移31位)
     *  7:0111  8:1000
     * @param a
     * @param b
     * @return
     */
    private static int AddM(int a, int b) {
        int c = a + b;
        return (c & 0x7FFFFFFF) + ((c & 0x80000000) >>> 31);
    }
 
    /**
     * 返回[(左移k位 )按位或(无符号右移31-k位)]和7FFFFFFF按位与的结果
     * @param x
     * @param k
     * @return
     */
    private static int MulByPow2(int x, int k) {
        return ((((x) << k) | ((x) >>> (31 - k))) & 0x7FFFFFFF);
    }
 
    
    /**
     * 初始化模式下,LFSR接收一个31比特字u
     * v = (2^15)*s[15]+(2^17)*s[13]+(2^21)*s[10]+(2^20)*s[4]+(1+2^8)*s[0] mod (2^31-1);
    s[16]=(v+u) mod (2^31-1);
     * @param u 由非线性函数F的32比特输出W舍弃最低位(右移一位)得到
     * 
     */
    private static void LFSRWithInitializationMode(int u) {
        int f, v;
        f = LFSR_S[0];
        v = MulByPow2(LFSR_S[0], 8);
        f = AddM(f, v);
        v = MulByPow2(LFSR_S[4], 20);
        f = AddM(f, v);
        v = MulByPow2(LFSR_S[10], 21);
        f = AddM(f, v);
        v = MulByPow2(LFSR_S[13], 17);
        f = AddM(f, v);
        v = MulByPow2(LFSR_S[15], 15);
        f = AddM(f, v);
        //此时完成v的计算
        f = AddM(f, u);
         //状态转换(s[1],s[2],...,s[16])-→(s[0],s[1],...,s[15])  这里s[16]即为现在的f
        for (int i = 0; i < 15; ++i) {
            LFSR_S[i] = LFSR_S[i + 1];
        }
        LFSR_S[15] = f;
    }
 
   
    /**
     * 工作模式下 无输入
     */
    private static void LFSRWithWorkMode() {
        int f, v;
        f = LFSR_S[0];
        v = MulByPow2(LFSR_S[0], 8);
        f = AddM(f, v);
        v = MulByPow2(LFSR_S[4], 20);
        f = AddM(f, v);
        v = MulByPow2(LFSR_S[10], 21);
        f = AddM(f, v);
        v = MulByPow2(LFSR_S[13], 17);
        f = AddM(f, v);
        v = MulByPow2(LFSR_S[15], 15);
        f = AddM(f, v);
        /**状态更新*/
        for (int i = 0; i < 15; ++i) {
            LFSR_S[i] = LFSR_S[i + 1];
        }
        LFSR_S[15] = f;
    }
 
    /**
     * Bit Reorganization Procedure 比特重组
     * & 0x7FFF8000 << 1 截取高16位   >>>15
     * & 0xFFFF <<16 截取低十六位
     */
    private static void BitReorganization() {
        BRC_X[0] = ((LFSR_S[15] & 0x7FFF8000) << 1) | (LFSR_S[14] & 0xFFFF);
        BRC_X[1] = ((LFSR_S[11] & 0xFFFF) << 16) | (LFSR_S[9] >>> 15);
        BRC_X[2] = ((LFSR_S[7] & 0xFFFF) << 16) | (LFSR_S[5] >>> 15);
        BRC_X[3] = ((LFSR_S[2] & 0xFFFF) << 16) | (LFSR_S[0] >>> 15);
    }
 
    /**
     * 非线性函数
     * @return
     */
    private static long F() {
        long W, W1, W2, u, v;
        W = (BRC_X[0] ^ F_R1) + F_R2;
        W = W & 0x00000000FFFFFFFFL;
        W1 = F_R1 + BRC_X[1];
        W1 = W1 & 0x00000000FFFFFFFFL;
        W2 = F_R2 ^ BRC_X[2];
        W2 = W2 & 0x00000000FFFFFFFFL;
        u = L1((W1 << 16) & 0x00000000FFFFFFFFL | (W2 >>> 16));
        u = u & 0x00000000FFFFFFFFL;
        v = L2((W2 << 16) & 0x00000000FFFFFFFFL | (W1 >>> 16));
        v = v & 0x00000000FFFFFFFFL;
        F_R1 = MAKEU32(S0[(int) (u >>> 24)], S1[(int) ((u >>> 16) & 0xFF)], S0[(int) ((u >>> 8) & 0xFF)], S1[(int) (u & 0xFF)]);
        F_R2 = MAKEU32(S0[(int) (v >>> 24)], S1[(int) ((v >>> 16) & 0xFF)], S0[(int) ((v >>> 8) & 0xFF)], S1[(int) (v & 0xFF)]);
        return W;
    }
   
    /**
     * a循环左移k位
     * @param a
     * @param k
     * @return a循环左移k位的结果
     */
    private static long ROL(long a, int k) {
        return (((a) << k) | ((a) >>> (32 - k)));
    }
 
    /** 线性变换 L1 */
    private static long L1(long X) {
        return (X ^ ROL(X, 2) ^ ROL(X, 10) ^ ROL(X, 18) ^ ROL(X, 24));
    }
 
    /** 线性变换 L2 */
    private static long L2(long X) {
        return (X ^ ROL(X, 8) ^ ROL(X, 14) ^ ROL(X, 22) ^ ROL(X, 30));
    }
 
    /** 产生32比特的字 */
    private static int MAKEU32(int a, int b, int c, int d) {
        return (int) (((long) a << 24) | ((long) b << 16) | ((long) c << 8) | ((long) d));
    }
 
    /** 产生31比特的字 */
    private static int MAKEU31(int a, int b, int c){
         return (int)(((long)(a) << 23) | ((long)(b) << 8) | (long)(c));
    }
     
    /**
     * 初始化阶段
     * 将初始密钥和初始向量装入LFSR作为其初态,并置R1和R2为0,然后进行一系列操作。
     * @param k
     * @param iv
     */
    public static void Initialization(int[] k, int[] iv) {
        long w;
 
        /** 循环设置LFSR初态 */
        for (int i = 0; i < 16; ++i) {
            LFSR_S[i] = MAKEU31(k[i], EK_d[i], iv[i]);
        }
        
        long nCount = 32;
        while (nCount > 0) {
            BitReorganization();
            w = F();
            LFSRWithInitializationMode((int) (w >>> 1));
            nCount--;
        }//循环32次
        BitReorganization();
        F();
        LFSRWithWorkMode();
    }
 
    /**
     * 工作阶段产生密钥流
     * @param pKeyStream
     * @param KeyStreamLen
     */
    public static void GenerateKeyStream(long[] pKeyStream, long KeyStreamLen) {
        long W;
    	BitReorganization();
		F(); 			
		LFSRWithWorkMode();
		W = F();
		//System.out.println("初始密钥字:"+W);
        //System.out.println("--------------------------------------");
        for (int i = 0; i < KeyStreamLen; ++i) {
            BitReorganization();//比特重组
            pKeyStream[i] = F() ^ BRC_X[3] & 0x00000000ffffffffL;
            LFSRWithWorkMode();
        }
    	
    }
    
    /**
     * 加密方法 
     * @param M 明文
     * @param keys 密钥
     * @return C 密文
     */
    public static long[] Encry(String M,long[]keys)
    {    
       int length = M.length();
       long[] C = new long[length];
       char[] chars = M.toCharArray();
       System.out.println("--------------------------");
       System.out.println("ZUC加密结果:");
       for (int i = 0; i < length; i++) {
    	C[i] = chars[i] ^ keys[i];
    	System.out.print(Integer.toHexString((int)C[i])+" ");
    }
    return C;
    }
    
	/**
	 * 解密方法
	 * @param C 密文
	 * @param keys 密钥
	 * @return M 明文
	 */
	public static char[] Decry(long[] C,long[]keys)
	{
	    int length = C.length;
	    char[] M = new char[length];
	    System.out.println("--------------------------");
	    System.out.println("解密结果:");
	    for (int i = 0; i < length; i++) {
	        M[i] = (char) (C[i] ^ keys[i]);
	        System.out.print(M[i]);
	    }
	    return M;
	}   
}

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值