auto base = juce::BigInteger{3};
auto exponent = juce::BigInteger{8};
auto modulus = juce::BigInteger{5};
base.exponentModulo(exponent, modulus);
// Result is 2, should be 1
auto base = juce::BigInteger{static_castjuce::int64(85899345927)};
auto exponent = juce::BigInteger{static_castjuce::int64(85899345926)};
auto modulus = juce::BigInteger{static_castjuce::int64(85899345925)};
base.exponentModulo(exponent, modulus);
// Result is 2, should be 67108864 (0x4000000)
Tests for fix are in my side project aiming to port key file generation to node.
Re-ran fuzz tests for 4hrs again just to be sure (on hex strings ranging 300-1000 chars).
I have some tests by myself with bigger keys. They work and I can use them together with other frameworks. I compared the result with the .Net framework.
I’m not using plain numbers. I’m using byte arrays. I’m pretty sure it is an endian problem. You need to reverse the result. Maybe padding is also required.
You will find some examples in this forum. Here is the decryption code of a key created with the Microsoft c# RSA library:
Please, if the following is wrong, then I am wrong, there is no other way here (juce 8.0.2):
auto base = juce::BigInteger{3};
auto exponent = juce::BigInteger{8};
auto modulus = juce::BigInteger{5};
base.exponentModulo(exponent, modulus);
// Result is 2, should be 1
auto base = juce::BigInteger{static_castjuce::int64(85899345927)};
auto exponent = juce::BigInteger{static_castjuce::int64(85899345926)};
auto modulus = juce::BigInteger{static_castjuce::int64(85899345925)};
base.exponentModulo(exponent, modulus);
// Result is 2, should be 67108864 (0x4000000)
I agree with your initial assessment, I think this function is broken when the modulus is smaller than the exponent. I’m not too familiar with cryptography, but perhaps this is an uncommon situation? In any case, the fix you suggested looks sensible, and I expect we’ll merge that or something very similar. I’ll update this thread once the change is published.
In case it’s helpful, I used the following procedure to create some tests. Run the following using python3 to generate some tuples of inputs and expected results:
import random
for i in range(100):
b = random.getrandbits(256)
e = random.getrandbits(256)
m = random.getrandbits(256)
print(f'{{ "{b:x}", "{e:x}", "{m:x}", "{pow(b, e, m):x}" }},')
Then, paste the tuples into the TestCase array in this C++ snippet:
ok i’m using fast-check in typescript. The JuceBigInteger class is named for being a port that uses the jsbn package. The actual juce::BigInteger is coming from execTestBin:
Forget my tests, they don’t pass… you are probably right. It has to do with the key text and key length. We encrypt text that is smaller than the key and probably have no problem because of this.