简体   繁体   English

RSA数字签名失败

[英]RSA digital signature failing

I am trying to implement the RSA Blind digital signature scheme, using the BigInteger class for generating large prime numbers. 我正在尝试使用BigInteger类生成大型素数来实现RSA Blind数字签名方案。 Samantha generates the public key, the private key, chooses a message, masks it, then signs it and then Victor verifies the signature. 萨曼莎(Samantha)生成公用密钥,专用密钥,选择一条消息,对其进行屏蔽,然后对其签名,然后Victor验证签名。

Problem: As long as I use the modular exponentiation method modPow from the BigInteger class, everything works perfectly (the verification algorithm returns true everytime). 问题:只要我使用BigInteger类的模幂运算方法modPow ,一切都可以正常运行(验证算法每次都会返回true)。 However, I have built a custom class where I have implemented several algebraic algorithms on my own; 但是,我建立了一个自定义类,在其中我自己实现了几种代数算法。 when I switch the modPow call with my modExp method, I keep getting false returns from the verification algorithm (about 50-60 % of the time), even though I should not. 当我使用modExp方法切换modPow调用时,即使没有这样做,我仍然会从验证算法中得到错误的回报(大约50-60%的时间)。 If instead of using large, random integers, I set small, hardcoded numbers for testing purposes, I get the correct result. 如果我不是使用较大的随机整数,而是为了测试目的而设置较小的硬编码数字,则可以得到正确的结果。

Question: As a consequence, I am pretty sure that my modExp method is the problem, however I can't seem to find out did I do wrong, even after changing the algorithm several times. 问题:结果,我非常确定我的modExp方法是问题所在,但是即使多次更改算法后,我也似乎找不到我做错了什么。 What is the problem? 问题是什么?

My code so far: 到目前为止,我的代码:

RSA_test() -- Method used for the precomputation step and testing 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);
}

As the signature and verification methods are irrelevant for the question, as I am certain that they are correct, I will omit them. 由于签名和验证方法与该问题无关,因此我确定它们是正确的,因此我将省略它们。 Also, here is my modExp method: 另外,这是我的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);
}

You don't handle negative exponents correctly, except to check that gcd(base, modulus) == 1 . 您不能正确处理负指数,除非检查gcd(base, modulus) == 1 The following snippet shows one correct way to do it. 以下代码段显示了一种正确的方法。

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

Observe that the signum() method may be more convenient for comparing big integers to zero. 请注意,使用signum()方法比较大整数和零可能更方便。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM