现在的位置: 首页 > 综合 > 正文

[密码学]McEliece公钥密码体制

2018年02月15日 ⁄ 综合 ⁄ 共 4226字 ⁄ 字号 评论关闭

(注:本文仅作为学习使用,若转载拷贝等引起的一切后果由读者自负。)

最近学习了McEliece公钥密码体制,一种不对称加密算法于代数编码理论,使用了一系列纠错代码Goppa。这种加密系统使用Goppa代码作为专用密钥。其安全性基于纠错编码(error
correcting codes)理论。

假设有长度1024的二元字符串,它有50个错误地方,则错误位置的情况就有,所以其破解起来还是有点困难的。直接进入正题。


一、加密解密过程

假设通信双方分别是Bob和Alice,Bob首先选择一个生成矩阵G(该矩阵用于产生一个线性纠错码C,其码的重量为d),再选择一个k*k矩阵S(可逆矩阵),还有一个n*n矩阵P(可置换阵,这意味着P的每行每列都只有一个1)。我们定义就是公钥,S、G和P都需要保密(既这些是密钥)。

(a).
现在Alice需要向Bob发送一个消息x,Alice则进行下面的操作:(1)她产生一个随机二元字符串e,其长度为n,重量为t;(2)计算。y就是我们的密文。

(b).
Bob收到密文y,如何解密?(1)计算(因为P是置换阵,所以有);(2)应用线性纠错理论(这部分可以参考下线性纠错码的相关知识,比较经典的是Hamming码,下面我们会用这个来举例)去对纠错,纠错后得到;(3)计算

、安全性简述

该公钥的安全性主要依赖于破解获得。(这和前面我们所说是一样的,长度为1024二元字符串中如有50个error,我们是很难破解的,但是随着量子计算机发展,该密钥体制可以被破解(2008年某学者提出相应的算法),有兴趣的读者可以参考下相应的文献)。该密钥体制的安全性主要依赖与S(如果GP泄漏,那么可以很容易求出S,所以G、S和P都必须保密)。为了使得更加安全,我们需要选择更大的d(C)(指的是码字C的重量),McEliece建议使用[1024,
512, 101]的Goppa码。Goppa码有三个参数。如果m=10,t=50,则Goppa码就是[1024,524,101]。当然该密钥体制也有着一定的弊端,为了一定的安全性,需要一个特别大的公钥矩阵,这点相比RSA等其它体制,是不好的。


三、例子

Step 1:公钥私钥产生阶段:

生成矩阵G如下:

(熟悉线性纠错码的读者应该发现了,这个就是其实是[7,4]Hamming码)。Bob再选择私钥S、P,分别选择如下(注意:S一定要是可逆,P一定是置换阵)

                                             

通过S、G和P我们计算出公钥如下:

                                                 

Step 2:密文产生阶段

假设Alice想向Bob发送消息m=(1,0,1,1),首先选择一个随机的错误码e,,假定e=(0,1,0,0,0,0,0),(为什么只有1个"1"呢?答:Hamming码的纠错能力有限,只可以纠1位)。运用公式,得到密文y=(0,0,0,1,1,0,0)。

Step:解密阶段

Bob收到密文y后,计算,得到=(0,
0, 1, 0, 0, 0, 1)。用G的校验矩阵H去进行校验,H的形式如下:

                                                                                        

针对这个例子,我们发现其第六位是错的,纠正,得到=(0, 0, 1, 0, 0, 1, 1)。紧接着计算,得到

                                                                                      

x就是我们所解密得到的明文了!

四、JAVA代码示例

针对上面的例子,笔者编写了一个JAVA程序来测试。该问题中具有非常多的矩阵运算,因此笔者采用了JAMA包来帮忙解决这个问题。JAMA的下载地址:http://math.nist.gov/javanumerics/jama/   

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import Jama.Matrix;

public class McEliece {
	private static Matrix G;
	private static Matrix H;
	private static Matrix S;
	private static Matrix P;
	private static Matrix G1;
	private static Matrix e;
	private static Matrix y;
	private static Matrix y1;
	private static Matrix x1;
	private static Matrix x0;
	private static Matrix x;
	private final static int LENGTH = 4;

	public void generator(int type) {
		double[][] array = null;
		double[][] arrayH = null;
		if (type == 1) {
			array = new double[][] { { 1, 0, 0, 0, 1, 1, 0 },
					{ 0, 1, 0, 0, 1, 0, 1 }, { 0, 0, 1, 0, 0, 1, 1 },
					{ 0, 0, 0, 1, 1, 1, 1 } };
			arrayH = new double[][] { { 1, 1, 0 }, { 1, 0, 1 }, { 0, 1, 1 },
					{ 1, 1, 1 }, { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
		}
		G = new Matrix(array);
		H = new Matrix(arrayH);
	}

	public void CreateSandP() {
		double[][] array = { { 1, 0, 0, 1 }, { 1, 1, 0, 1 }, { 0, 1, 0, 1 },
				{ 1, 1, 1, 0 } };
		S = new Matrix(array);
		double[][] array1 = { { 0, 0, 1, 0, 0, 0, 0 }, { 1, 0, 0, 0, 0, 0, 0 },
				{ 0, 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 1, 0 },
				{ 0, 0, 0, 0, 0, 0, 1 }, { 0, 1, 0, 0, 0, 0, 0 },
				{ 0, 0, 0, 1, 0, 0, 0 } };
		P = new Matrix(array1);
	}

	private void Mod2(Matrix ma) {
		for (int i = 0; i < ma.getRowDimension(); i++)
			for (int j = 0; j < ma.getColumnDimension(); j++)
				ma.set(i, j, Math.abs(((int) ma.get(i, j)) % 2));
	}

	public void CaculateG1() {
		G1 = S.times(G).times(P);
		Mod2(G1);
	}

	public void GenerErrorVector() {
		double[][] array = { { 0, 1, 0, 0, 0, 0, 0 } };
		e = new Matrix(array);
	}

	public void CaculateCiphertext() {
		y = x.times(G1).plus(e);
		Mod2(y);
	}

	public void decrypt() {
		int ErrorPosition = 0;
		y1 = y.times(P.inverse());
		Mod2(y1);
		Matrix Syndrome = y1.times(H);// 计算得到校验子
		Mod2(Syndrome);
		// 与校验矩阵对比,进行校正
		for (int i = 0; i < H.getRowDimension(); i++) {
			boolean flag = true;
			for (int j = 0; j < H.getColumnDimension() && flag; j++) {
				if (H.get(i, j) != Syndrome.get(0, j))
					flag = false;
			}
			if (flag) {
				ErrorPosition = i;
				break;
			}
		}
		System.out.println("错误的位置:" + ErrorPosition);
		x1 = y1.copy();
		x1.set(0, ErrorPosition,
				(double) ((int) (y1.get(0, ErrorPosition)) + 1) % 2);
		System.out.print("x1矩阵如下");
		x1.print(0, 0);
		x0 = x1.getMatrix(0, 0, 0, LENGTH - 1);
		System.out.print("x0矩阵如下");
		x0.print(0, 0);
		System.out.print("解密得到明文:");
		x = x0.times(S.inverse());
		Mod2(x);
		x.print(0, 0);
	}

	// test
	public static void main(String args[]) {
		/**
		 * 生成矩阵 这里我们使用2种hamming码
		 */
		McEliece test = new McEliece();
		test.generator(1);

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		test.CreateSandP();
		test.CaculateG1();
		test.GenerErrorVector();
		System.out.print("G1矩阵(公钥):如下");
		G1.print(0, 0);
		System.out.print("e矩阵:如下");
		e.print(0, 0);

		System.out.println("Alice: input message:");// 明文
		try {
			String secret = br.readLine();
			double[][] array_x = new double[1][LENGTH];
			for (int i = 0; i < LENGTH; i++) {
				array_x[0][i] = Double.parseDouble(secret.charAt(i) + "");
			}

			x = new Matrix(array_x);
		} catch (IOException e) {
			e.printStackTrace();
		}

		// 计算得到的密文
		test.CaculateCiphertext();
		System.out.print("得到的密文:如下");
		y.print(0, 0);

		// 解密
		System.out.print("Bob解密结果如下");
		test.decrypt();
	}

}

测试结果如下:

只给出了一个简单的实现程序,作为理解该密钥体制使用,不做其它用途。

笔者水平有限,欢迎交流!

抱歉!评论已关闭.