栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

eclipse实现Schnorr数字签名

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

eclipse实现Schnorr数字签名

Schnorr数字签名,供大家参考,具体内容如下

一、实验目的

学习Schnorr算法在数字签名方面的使用,掌握公钥签名中最基础的签名算法-Schnorr数字签名算法的编写。

二、实验要求

1. 熟悉Schnorr算法的描述,已经其使用场景。
2. 熟悉Schnorr数字签名算法。
3. 掌握如何使用java语言,实现Schnorr签名算法。

三、开发环境

JDK1.8,eclipse。

四、实验原理

数字签名是指消息发送方利用特定参数产生的一段消息码,该消息码可以用来标识消息发送者真实身份,同时可以标识发送的数据的完整性,所以在一定程度防止了发送的数据在发送过程中被攻击者篡改的行为。简而言之,数字签名就是由消息发送者利用身份信息与消息相结合产生的一个消息摘要。

在数字签名过程中核心的两个步骤就是产生签名信息和对签名信息的验证,产生签名就是消息发送方使用特定的签名算法将数据产生成消息摘要,同时使用私钥对其摘要进行加密,最后将加密后的密文和原始的数据一起发送。消息接收方收到信息后,首先用发送者的公钥来算数据的摘要,然后把此结果与收到的摘要对比,如果一致,则验证通过,认为该消息是真实有效的。反之无效,丢弃该消息。过程如下图1所示。

a) 数字签名加密过程

b) 数字签名解密验证过程

图1 数字签名过程

Schnorr签名算法是由德国数学家、密码学家Claus Schnorr提出,是Elgamal签名方案的变种。

具体步骤如下:

首先是生成公钥/私钥对,过程如下:

a. 选择素数 和 ,其中 是 的素因子;
b. 选择一个整数 ,使得 ; 、 和 构成全局公钥参数,在用户组内的每个用户都可以使用;
c. 选择随机整数 作为用户的私钥,其中 ;
d. 计算公钥 ;

对于密钥对为 的用户,通过以下过程产生签名:

a. 选择随机整数,计算 ;
b. 将 附在消息后面,一起计算Hash值 :

c. 计算。

签名对为 ,其他用户通过以为过程来验证签名:
a. 计算;
b. 验证等式 是否成立。

代码段:

SchnorrSignature

import java.io.File;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.List;


public class SchnorrSignature {
 // 路径前缀
 private static final String PERFIX_PATH = GetProjectPath.getPath() + "/ra/";
 // 存放公共参数
 private static final String PARAM_PATH = PERFIX_PATH + "initParams.properties";
 // 存放公钥的路径
 private static final String PUBLIC_KEY_PATH = PERFIX_PATH + "publicKey.properties";
 
 
 public static void initPara(int blq) {
 File file = new File(PARAM_PATH);
 if(file.exists()) {
 System.out.println("已经存在初始化参数,为不影响已经颁发的证书,如果你强制要重新产生参数,请备份所有文件到其他路径下,并重新生产密钥对并重新签名");
 }else {
 System.out.println("系统初始化中,生产公共参数... ...");
 BigInteger one = new BigInteger("1");
 BigInteger two = new BigInteger("2");
 BigInteger q, qp, p, a, g;
 int certainty = 100;
 SecureRandom sr = new SecureRandom();
 // blq长度的q, q是p-1的素因子 
 //生成BigInteger伪随机数,它可能是(概率不小于1 - 1/2certainty)一个具有指定 bitLength 的素数
 q = new BigInteger(blq, certainty, sr);
 qp = BigInteger.ONE;
 do { // 选择一个素数 p 
 p = q.multiply(qp).multiply(two).add(one);
 if(p.isProbablePrime(certainty))
 break;
 qp = qp.add(BigInteger.ONE);
 } while(true);
 
 while(true) {
 a = (two.add(new BigInteger(blq, 100, sr))).mod(p);// (2+x) mod p
 BigInteger ga = (p.subtract(BigInteger.ONE)).divide(q);// (p-1)/q
 g = a.modPow(ga, p); // a^ga mod p = 1 
 if(g.compareTo(BigInteger.ONE) != 0) // g!=1
 break;
 }
 // 存放公共参数
 List transArryToLi = KeyPairOperate.transArryToLi(new String[] {"blq=" + blq,"q=" + q, "p=" + p, "g=" + g});
 KeyPairOperate.writePublicKeyToFile(PARAM_PATH, transArryToLi, false);
 System.out.println("...");
 System.out.println("初始化完成!");
 }
 }
 
 
 public static void generateKeyForUser(String user) {
 File file = new File(PERFIX_PATH + user + ".properties");
 if(file.exists()) {
 System.out.println(user + "已经颁发了密钥,请备份所有文件到其他路径下,并重新签名");
 }else {
 System.out.println("密钥颁发中,请稍后");
 System.out.println("... ...");
 BigInteger sk,pk;// 私钥和公钥
 int blq = Integer.parseInt(KeyPairOperate.getDataFromFile(PARAM_PATH, "blq"));
 SecureRandom sr = new SecureRandom();
 // 随机数作为私钥
 sk = new BigInteger(blq, sr);
 
 // 私钥的话名字命名
 List toLiSK = KeyPairOperate.transArryToLi(new String[] {"sk=" + sk});
 KeyPairOperate.writePublicKeyToFile(PERFIX_PATH + user + ".properties", toLiSK, false);
 
 BigInteger g = new BigInteger(KeyPairOperate.getDataFromFile(PARAM_PATH, "g"));
 BigInteger p = new BigInteger(KeyPairOperate.getDataFromFile(PARAM_PATH, "p"));
 // 公钥
 pk = g.modPow(sk, p);// g^w mod p -- 注意这儿是正,所以下面验证的时候是用的负
 List toLiPK = KeyPairOperate.transArryToLi(new String[] {user + "=" + pk});
 KeyPairOperate.writePublicKeyToFile(PUBLIC_KEY_PATH, toLiPK, true);
 System.out.println(user + " 密钥颁发完成");
 }
 }
 
 
 public static void makeSign(String sourcefilePath, String user) {
 System.out.println(user+ "的文件" + KeyPairOperate.getFileName(sourcefilePath) + " 签名开始");
 System.out.println("... ...");
 BigInteger q = new BigInteger(KeyPairOperate.getDataFromFile(PARAM_PATH, "q")); // 素数 q
 BigInteger p = new BigInteger(KeyPairOperate.getDataFromFile(PARAM_PATH, "p")); // 素数 p
 BigInteger g = new BigInteger(KeyPairOperate.getDataFromFile(PARAM_PATH, "g")); // q的原根 a
 
 // 私钥
 BigInteger sk = new BigInteger(KeyPairOperate.getDataFromFile(PERFIX_PATH + user + ".properties", "sk")); // 私钥
 
 SecureRandom sr = new SecureRandom();
 BigInteger r, x, e, y; 
 r = new BigInteger(q.bitLength(), sr); // 随机数
 x = g.modPow(r, p); // g^r mod p
 // e=H(M||x)
 try {
 MessageDigest md5 = MessageDigest.getInstance("MD5");
 md5.update(Files.readAllBytes(Paths.get(sourcefilePath)));
 md5.update(x.toString().getBytes());
 byte[] digest = md5.digest();
 // e 将BigInteger的符号大小表示法转换成一个BigInteger值
 e = new BigInteger(1, digest); 
 // y s2 = r
 y = (r.subtract(sk.multiply(e))).mod(q);
 List transArryToLi = KeyPairOperate.transArryToLi(new String[] {"e="+e,"y="+y});
 String fileName =PERFIX_PATH + user + "_sign_" + KeyPairOperate.getFileName(sourcefilePath) + ".properties";
 KeyPairOperate.writePublicKeyToFile(fileName, transArryToLi, false);
 System.out.println(user+ "的文件" + KeyPairOperate.getFileName(sourcefilePath) + "签名成功 !");
 } catch (Exception e1) {
 e1.printStackTrace();
 }
 }
 
 
 public static void checkSign(String sourcefilePath, String user) {
 System.out.println("验证签名");
 
 BigInteger p = new BigInteger(KeyPairOperate.getDataFromFile(PARAM_PATH, "p")); // 素数 p
 BigInteger g = new BigInteger(KeyPairOperate.getDataFromFile(PARAM_PATH, "g")); // q的原根 a
 
 BigInteger pk = new BigInteger(KeyPairOperate.getDataFromFile(PUBLIC_KEY_PATH, user));// 公钥
 
 String fileName =PERFIX_PATH + user + "_sign_" + KeyPairOperate.getFileName(sourcefilePath) + ".properties"; 
 
 BigInteger e = new BigInteger(KeyPairOperate.getDataFromFile(fileName, "e")); // e 签名信息1: 产生的签名信息
 BigInteger y = new BigInteger(KeyPairOperate.getDataFromFile(fileName, "y"));; // y 签名信息2: 加密后的消息
 
 // 计算的 x'
 BigInteger x1 = g.modPow(y, p); // g^y mod p -- y
 BigInteger x2 = (pk.modPow(e, p)).mod(p); // pk^e mod p 
 BigInteger x = x1.multiply(x2).mod(p); // x1*x2 mod p = (g^y)*(pk^e)mod p
 
 try {
 MessageDigest md5 = MessageDigest.getInstance("MD5");
 md5.update(Files.readAllBytes(Paths.get(sourcefilePath)));
 md5.update(x.toString().getBytes());
 byte[] digest = md5.digest();
 BigInteger h = new BigInteger(1, digest);
 System.out.println("... ...");
 if(e.equals(h))
 System.out.println(user+ "的文件" + KeyPairOperate.getFileName(sourcefilePath) + "验证通过 !");
 else
 System.out.println(user+ "的文件" + KeyPairOperate.getFileName(sourcefilePath) + "验证失败 !");
 } catch (Exception e1) {
 e1.printStackTrace();
 }
 }
}

GetProjectPath:

import java.io.File;


public class GetProjectPath {
 
 public static String getPath() {
 File directory = new File("");
 String courseFile = null;
 try {
 courseFile = directory.getCanonicalPath().replace("\", "/");
 }catch (Exception e) {
 e.printStackTrace();
 }
 return courseFile;
 }

}

KeyPairOperate

import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;


public class KeyPairOperate {
 
 public static String getFileName(String path) {
 int indexOf = path.lastIndexOf("\")+1;
 int last = path.lastIndexOf(".");
 return path.substring(indexOf, last);
 }
 
 
 public static List transArryToLi(String[] para){
 List li = new ArrayList();
 for(int i=0; i param, Boolean flag) {
 try {
 PrintWriter printWriter = new PrintWriter(new FileWriter(path,flag));
 for(String element : param) {
 printWriter.println(element);
 }
 printWriter.close();
 } catch (Exception e) {
 e.printStackTrace();
 }
 }
}

Shtest

import org.junit.Test;
public class Shtest {
 String pathFile ="C:\Users\89763\Desktop\www.rtf";
 
 @Test
 public void initPara() {
 SchnorrSignature.initPara(12);
 }
 @Test
 public void generateKeyForUser() {
 SchnorrSignature.generateKeyForUser("xiaoming");
 SchnorrSignature.generateKeyForUser("xiaowang");
 }
 @Test
 public void makeSign() {
 SchnorrSignature.makeSign(pathFile,"xiaoming");
 SchnorrSignature.makeSign(pathFile,"xiaowang");
 }
 @Test
 public void checkSign() {
 
 SchnorrSignature.checkSign( pathFile ,"xiaoming");
 SchnorrSignature.checkSign( pathFile ,"xiaowang");
 }

}

以上代码均来自https://blog.csdn.net/qq_27731689/article/details/106828368  作者:黎明小书生

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/133607.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号