【问题标题】:RSA digital signature failingRSA 数字签名失败
【发布时间】:2017-11-01 18:17:44
【问题描述】:

我正在尝试实现 RSA 盲数字签名方案,使用 BigInteger 类生成大素数。 Samantha 生成公钥、私钥,选择一条消息,屏蔽它,然后对其进行签名,然后 Victor 验证签名。

问题:只要我使用BigInteger 类中的模幂方法modPow,一切正常(验证算法每次都返回真)。但是,我建立了一个自定义类,我自己实现了几个代数算法;当我用我的 modExp 方法切换 modPow 调用时,我不断从验证算法中得到错误的返回(大约 50-60% 的时间),即使我不应该.如果我不使用大的随机整数,而是设置小的硬编码数字用于测试目的,我会得到正确的结果。

问题: 因此,我很确定我的 modExp 方法是问题所在,但我似乎无法发现我做错了什么,甚至多次更改算法后。有什么问题?

到目前为止我的代码:

RSA_test() -- 用于预计算步骤和测试的方法

public static void RSA_test(){

    // The Signer (Samantha) picks p and q, 1024 bit primes
    Random rng = new SecureRandom();
    BigInteger p = BigInteger.probablePrime(1024, rng);
    BigInteger q = BigInteger.probablePrime(1024, rng);
  /*BigInteger p = BigInteger.valueOf(7);
    BigInteger q = BigInteger.valueOf(13);*/

    // The RSA modulus is computed
    BigInteger n = p.multiply(q);

    // phi(n) is computed
    BigInteger phiN = (p.subtract(BigInteger.ONE)
                      .multiply(q.subtract(BigInteger.ONE)));

    // Samantha chooses her message, m
    BigInteger m = new BigInteger("22");

    // Samantha computes her public exponent
    BigInteger v;
    while(true){
        v = new BigInteger(phiN.bitLength(), rng);
        if(v.compareTo(BigInteger.ONE) > 0 &&
           v.compareTo(phiN) < 0 &&
           ModularArithmetic.gcd(v, phiN).equals(BigInteger.ONE))
            break;
    }
    // v = BigInteger.valueOf(5);

    // Samantha generates the blinding factor and masks her message
    BigInteger r;
    while(true){
        r = new BigInteger(512, rng);
        if(ModularArithmetic.gcd(r, n).equals(BigInteger.ONE))
            break;
    }
    // r = BigInteger.valueOf(10);

    BigInteger mBlinded = m.multiply(ModularArithmetic.modExp(r, v, n));

    // Samantha signs her message
    BigInteger SBlinded = Cryptography.RSASignature(mBlinded, n, phiN, v);

    // Samantha removes the blinding factor, obtaining S
    BigInteger S = SBlinded.multiply(ModularArithmetic.modInv(r, n));

    // Victor verifies the signature
    boolean result = Cryptography.RSAVerification(S, m, n, v);

    String s = (result == true) ? "The signature has been verified" : "The signature has not been verified";
    System.out.println(s);
}

由于签名和验证方法与问题无关,因为我确信它们是正确的,所以我将它们省略。另外,这是我的 modExp 方法:

public static BigInteger modExp(BigInteger base, BigInteger exponent, BigInteger modulus){

    if(exponent.equals(BigInteger.ZERO))
        return (modulus.equals(BigInteger.ONE)) ? BigInteger.ZERO : BigInteger.ONE;
    if(base.equals(BigInteger.ONE))
        return (modulus.equals(BigInteger.ONE)) ? BigInteger.ZERO : BigInteger.ONE;
    if(exponent.equals(BigInteger.ONE))
        return base.mod(modulus);
    if(modulus.equals(BigInteger.ONE))
        return BigInteger.ZERO;
    // The case when base does not have a multiplicative inverse
    if((modulus.compareTo(BigInteger.ZERO) <= 0) || 
       ((exponent.compareTo(BigInteger.ZERO) < 0 && !(gcd(base,modulus).compareTo(BigInteger.ONE) == 0))))
        throw new ArithmeticException("BigInteger: modulus not positive");

    BigInteger result = BigInteger.ONE;
    while(exponent.compareTo(BigInteger.ZERO) > 0){
        if(exponent.testBit(0))
            result = (result.multiply(base).mod(modulus));
        exponent = exponent.shiftRight(1);
        base = (base.multiply(base)).mod(modulus);
    }

    return result.mod(modulus);
}

【问题讨论】:

  • 你也有自己的gcd()实现吗?
  • 是的,我知道,你为什么这么问?
  • 好吧,您没有显示该代码,以防这也是我们需要看到的问题的一部分。
  • 我已经对其进行了测试,并将问题定位到了模块化扩展算法。正如您在答案中所说,这正是问题所在。干杯!

标签: java cryptography rsa biginteger modular-arithmetic


【解决方案1】:

你没有正确处理负指数,除了检查gcd(base, modulus) == 1。以下 sn-p 显示了一种正确的方法。

if (exponent.signum() < 0 && gcd(base,modulus).equals(BigInteger.ONE)) {
    return modExp(base.modInverse(modulus), exponent.negate(), modulus);
}

注意signum() 方法可能更方便将大整数与零进行比较。

【讨论】:

  • 是的,很好,我没想到。谢谢。
猜你喜欢
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 2020-10-01
  • 2012-11-24
  • 1970-01-01
  • 2019-11-24
  • 1970-01-01
  • 2010-12-02
相关资源
最近更新 更多