title: ALG_RSA_NOPAD in Java Card
body: <p>To compute efficiently a square in Java Card, I want to use the algorithm <code>ALG_RSA_NOPAD</code> with an exponent equals to <code>2</code> and a modulus greater than the expected result (so the modular reduction has no effect).</p>
  
  <p>But I'm not able to use the algorithm <code>ALG_RSA_NOPAD</code>. In fact, when I call the method <code>doFinal()</code> I get a <code>CryptoException</code> which is <code>ILLEGAL_VALUE</code>. In the Java Card 2.2.2 spec, it's said that:</p>
  
  <blockquote>
    <p>CryptoException.ILLEGAL_USE if one of the following conditions is met:</p>
    
    <p>• This Cipher algorithm does not pad the message and the message is not block aligned.</p>
    
    <p>• This Cipher algorithm does not pad the message and no input data has been provided in inBuff
    or via the update() method.</p>
    
    <p>• The input message length is not supported.</p>
    
    <p>• The decrypted data is not bounded by appropriate padding bytes.</p>
  </blockquote>
  
  <p>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...</p>
  
  <p>The corresponding code:</p>
  
  <pre><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);
  </code></pre>
  
  <p>So the <code>CryptoException</code> is raised at the last line, but I don't really understand why.</p>
  
  <p>(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.)</p>