Blind Sign(盲签名,盲签) 是一种特殊的数字签名技术,允许消息在被签名前对签名者保持隐藏状态,签名后签名仍对该特定消息有效。其核心思想是通过“盲化”操作,使签名者无法看到原始内容,但仍能生成合法签名,常用于需要保护隐私或实现匿名性的应用场景。

盲签名的过程通常包括以下步骤:首先,签名请求者对原始消息进行盲化处理,并将盲化后的消息提交给签名者;签名者对盲化消息进行签名;随后,请求者对签名结果进行“去盲”,获得原始消息的有效签名。整个过程中,签名者无法得知所签消息的具体内容。

盲签名广泛应用于电子投票、电子现金(如eCash)、匿名凭证等系统中,以确保用户隐私与不可追踪性。例如,在电子现金系统中,银行可通过盲签方式签署加密货币而不知晓具体交易细节,从而防止用户身份泄露,同时保证交易的合法性与防伪造能力。

常见的盲签名方案基于RSA、ElGamal等公钥密码算法构造。

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

$$$t=mk^{e} \pmod n
$$$

(2)Bob对 t 签名

$$$t^{d}=(mk^{e})^{d} \pmod n
$$$

(3)Alice通过计算揭开 $$$t^{d}$$$

$$$s=t^{d}/k \pmod n
$$$

(4)结果为:

$$$s=m^{d} \pmod n
$$$

证明:

$$$t^{d}≡(mk^{e})^{d}≡m^{d}k \pmod n
$$$


$$$t^{d}\times{}k^{−1}=m^{d}\times{}k\times{}k^{−1}≡m^{d} \pmod n
$$$


Java Sample:

public class BlindSign {

    public static void main(String[] args) {
        BigInteger e = new BigInteger("65537");
        BigInteger d = new BigInteger("60530511629930072241945671200867889027539295362393257858025617298274206834041");
        BigInteger n = new BigInteger("99418278299100976004220175767913358809660152882550697543248103911741071816073");
        BigInteger factor = new BigInteger("10879736607308378083");
        BigInteger m = new BigInteger("1234567890");

        BigInteger blindMsg = blindHideMsg(m, factor, e, n);
        BigInteger blindSig = blindSignature(blindMsg, d, n);
        BigInteger sig = blindRetriveSig(blindSig, factor, n);
        BigInteger realSig = m.modPow(d, n);
        System.out.println("Message            = " + m);
        System.out.println("Blind Hide Message = " + blindMsg);
        System.out.println("Blind Sign         = " + blindSig);
        System.out.println("Blind Retrive Sign = " + sig);
        System.out.println("Sign               = " + 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.multiply(factor.modInverse(n)).mod(n);
        return signature;
    }
}

Outputs:

Message            = 1234567890
Blind Hide Message = 15770710624832124090310228670897217355377164232670135463798104068560510146688
Blind Sign         = 6139941993099585616261360618307345010100687512790350833813455369950720416299
Blind Retrive Sign = 73713217373639814035571155058840977138482078089410370766097424658230579955022
Sign               = 73713217373639814035571155058840977138482078089410370766097424658230579955022