[英]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.