To compute efficiently a square in Java Card, I want to use the algorithm ALG_RSA_NOPAD
with an exponent equals to 2
and a modulus greater than the expected result (so the modular reduction has no effect).
But I'm not able to use the algorithm ALG_RSA_NOPAD
. In fact, when I call the method doFinal()
I get a CryptoException
which is ILLEGAL_VALUE
. In the Java Card 2.2.2 spec, it's said that:
CryptoException.ILLEGAL_USE if one of the following conditions is met:
• This Cipher algorithm does not pad the message and the message is not block aligned.
• This Cipher algorithm does not pad the message and no input data has been provided in inBuff or via the update() method.
• The input message length is not supported.
• The decrypted data is not bounded by appropriate padding bytes.
So I conclude that my message isn't block aligned. But what does block aligned mean for this algorithm? Does my message have the same length that the modulus? The exponent? I tried different things but I didn't find...
The corresponding code:
byte[] res_RSA = new byte[(short) 0x0080];
KeyPair rsa_KeyPair = new KeyPair(KeyPair.ALG_RSA,KeyBuilder.LENGTH_RSA_1024);
rsa_KeyPair.genKeyPair();
RSAPublicKey rsa_PubKey; rsa_PubKey = (RSAPublicKey) rsa_KeyPair.getPublic();
rsa_PubKey.setExponent(new byte[]{(byte) 0x02}, (short) 0x00000, (short) 0x0001);
rsa_PubKey.setModulus(new byte[] { (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF, }, (short) 0x0000, (short) 0x0080);
cipherRSA = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false);
x = new byte[] { (byte) 0x0C, (byte) 0xE2, (byte) 0x65, (byte) 0x92,
(byte) 0x98, (byte) 0x84, (byte) 0x4C, (byte) 0x6C,
(byte) 0x39, (byte) 0x31, (byte) 0x78, (byte) 0x22,
(byte) 0x99, (byte) 0x39, (byte) 0xAD, (byte) 0xAD,
(byte) 0x74, (byte) 0x31, (byte) 0x45, (byte) 0xD2,
(byte) 0xB9, (byte) 0x37, (byte) 0xB2, (byte) 0x92,
(byte) 0x7D, (byte) 0x32, (byte) 0xE9, (byte) 0x70,
(byte) 0x91, (byte) 0x7D, (byte) 0x78, (byte) 0x45,
(byte) 0xC9, (byte) 0x5C, (byte) 0xF9, (byte) 0xF2,
(byte) 0xFD, (byte) 0xB9, (byte) 0xAE, (byte) 0x6C,
(byte) 0xC9, (byte) 0x42, (byte) 0x64, (byte) 0xBA,
(byte) 0x2A, (byte) 0xCE, (byte) 0x5A, (byte) 0x71,
(byte) 0x60, (byte) 0x58, (byte) 0x56, (byte) 0x17,
(byte) 0x2E, (byte) 0x25, (byte) 0xDD, (byte) 0x47,
(byte) 0x23, (byte) 0x6B, (byte) 0x15, (byte) 0x76,
(byte) 0x8F, (byte) 0x2A, (byte) 0x87, (byte) 0xC7 };
cipherRSA.init(rsa_PubKey, Cipher.MODE_ENCRYPT);
cipherRSA.doFinal(x, (short) 0x0000,
(short) 0x0040, res_RSA, (short) 0x0000);
So the CryptoException
is raised at the last line, but I don't really understand why.
(Note that, in my code, I set the modulus to the greatest value of 128bytes length to be sure that the square won't be affected.)
Well, on my card the message has to have the same length than the modulus... I thought I tested this case but I mismatched offsets.
So even my message isn't long as the modulus (I couldn't compute a square) I have to fill the array with zeros.
Often RSA has only be verified to work against certain public exponents for a specific implementation of Java Card. It is very likely that this issue will disappear if when you use a larger public exponent such as 65537 (0x01, 0x00, 0x01
). Please consult the user manual of your chip / platform.
Note that such calculations without padding are not secure for RSA. That means that they may be hard to explain to certification bodies as well. You may have more luck with Diffie-Hellman implementations (if any).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With