基于RSA的盲签名算法Java实现

来源:互联网 发布:js字符串转unicode 编辑:程序博客网 时间:2024/06/02 02:46

目录

  • 目录
  • 盲签名概念
  • 基于RSA的盲签名原理
  • Java实现
  • 参考书目

盲签名概念

盲签名(Blind Signature): Alice有个数据想让Bob签名,但是不想让Bob知道真实的数据,于是有了盲签名的概念。盲签名在很多地方都有许多应用,如电子投票等。

一个通俗的解释是:Alice想让Bob在一张信件上签名,但是不想让B看到信件上面写的字,于是Alice在信件上面放了一张复写纸然后将信件和复写纸放到了信封中交给Bob。Bob在拿到了信封之后直接在信封上面签字,这样字迹就通过复写纸写到了信件上面,Alice拿到了信封之后就可以得到Bob签字过的信件。

基于RSA的盲签名原理

前提:Bob的公开密钥e,私钥d,和一个公开模数n,Alice打算让Bob盲签。

Created with Raphaël 2.1.0AliceAliceBobBob选取随机值作为盲化因子,计算隐藏消息t对t进行签名解盲

(1)Alice选取盲因子k然后计算m

t=mke(modn)

(2)Bob对t签名
td=(mke)d(modn)

(3)Alice通过计算揭开td
s=td/k(modn)

(4)结果为:
s=md(modn)

证明:

td(mke)dmdk(modn)

td/k=mdk/kmd(modn)

这个证明过程是存在问题的,问题会在代码是现阶段暴露出来,后面会有朔宁。

Java实现

import java.math.BigInteger;/** * 盲签名相关 * Created by forest on 2017/5/23. */public class blindSignature {    public static void main(String[] args){        System.out.println("这里是盲签名测试");        BigInteger e = new BigInteger("32663");        BigInteger d = new BigInteger("23");        BigInteger n = new BigInteger("42167");        BigInteger m = new BigInteger("123");       //签名的消息        BigInteger factor = new BigInteger("37");   //盲因子        BigInteger blindMsg = blindHideMsg(m, factor, e, n);        BigInteger blindSig = blindSignature(blindMsg, d, n);        BigInteger sig = blindRetriveSig(blindSig, factor, n);        System.out.println("盲签名 = " + sig);        BigInteger realSig = m.modPow(d, n);        System.out.println("原签名 = " + realSig);    }    /**盲签名-盲化*/    public static BigInteger blindHideMsg(BigInteger msg, BigInteger factor, BigInteger e, BigInteger n){        BigInteger hideMsg = msg.multiply(factor.modPow(e, n)).mod(n);        return hideMsg;    }    /**盲签名-签名*/    public static BigInteger blindSignature(BigInteger blindMsg, BigInteger d, BigInteger n){        BigInteger blindSig = blindMsg.modPow(d, n);        return blindSig;    }    /**盲签名-解盲得到签名*/    public static BigInteger blindRetriveSig(BigInteger blindSig, BigInteger factor, BigInteger n){        BigInteger signature = blindSig.divide(factor);        return signature;    }}

测试结果

这里是盲签名测试盲签名 = 957原签名 = 14633

我们可以看到这里的盲签名与原签名不一致,问题出在解盲的过程中不应该采用除法而应该采用乘法求逆元。正确代码如下:

/**盲签名-解盲得到签名*/    public static BigInteger blindRetriveSig(BigInteger blindSig, BigInteger factor, BigInteger n){        BigInteger signature = blindSig.multiply(factor.modInverse(n)).mod(n);        return signature;    }

结果为

这里是盲签名测试盲签名 = 14633原签名 = 14633

错误来源

td/k=mdk/kmd(modn)

正确的应该是
tdk1=mdkk1md(modn)

参考书目

《应用密码学-协议、算法与C源程序》第二版23.12节