1

I'm trying to load a private key (generated with RSA in an external application) in a javacard. I've written some normal java code to generate a keypair and to print the exponent and modulus of the private key:

public class Main {

public static void main(String[] args) throws NoSuchAlgorithmException {
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
    keyGen.initialize(512);
    KeyPair kp = keyGen.generateKeyPair();
    RSAPrivateKey privateKey = (RSAPrivateKey) kp.getPrivate();
    BigInteger modulus = privateKey.getModulus();
    BigInteger exponent = privateKey.getPrivateExponent();

    System.out.println(Arrays.toString(modulus.toByteArray()));
    System.out.println(Arrays.toString(exponent.toByteArray()));
}

}

I then copied the byte arrays to the javacard code

        try {
            RSAPrivateKey rsaPrivate = (RSAPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_512, false);

            byte[] exponent = new byte[]{113, 63, 80, -115, 103, 13, -90, 75, 85, -31, 83, 84, -15, -8, -73, -68, -67, -27, -114, 48, -103, -10, 27, -77, -27, 70, 61, 102, 17, 36, 0, -112, -10, 111, 40, -117, 116, -120, 76, 35, 54, -109, 115, 70, -11, 118, 92, -43, -15, -38, -67, 112, -13, -115, 7, 65, -41, 89, 127, 62, -48, -66, 8, 17};
            byte[] modulus = new byte[]{0, -92, -30, 28, -59, 41, -57, 95, -61, 2, -50, -67, 0, 6, 67, -13, 22, 61, -96, -15, -95, 20, -86, 113, -31, -91, -92, 77, 124, 26, -67, -24, 40, -42, -41, 115, -66, 109, -115, -111, -6, 33, -51, 63, -72, 113, -36, 22, 99, 116, 18, 108, 106, 97, 95, -69, -118, 49, 9, 83, 67, -43, 50, -36, -55};
            rsaPrivate.setExponent(exponent, (short) 0, (short) exponent.length);
            rsaPrivate.setModulus(modulus, (short) 0, (short) modulus.length);
        }
        catch (Exception e) {
            short reason = 0x88;
            if (e instanceof CryptoException)
                reason = ((CryptoException)e).getReason();
            ISOException.throwIt(reason);
        }

Now for some reason, a CryptoException is thrown when setting the modulus with reason 1. According to the API, this means CryptoException.ILLEGAL_VALUE if the input modulus data length is inconsistent with the implementation or if input data decryption is required and fails.

I really got no clue why this is failing. Generating the keys on card is not an option in this project.

And I know 512 bits is not safe anymore, it's just for testing purpose. It will be replaced by 2048 bits in the end.

ChristopherS
  • 853
  • 4
  • 16
  • Have you tried something like this? Get keyBytes: byte[] keyEncodedBytes = privateKey.getEncoded() Associate the pkcs11 provider to javacard and then: KeyFactory keyFactory = KeyFactory.getInstance("RSA", pkcs11Provider); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec ( key ); PrivateKey privateKey = keyFactory.generatePrivate (keySpec); – Egl Aug 07 '15 at 12:26
  • 1
    @Egl I want to reconstruct the private key on the javacard. The classes you are talking about are not available on it. – ChristopherS Aug 07 '15 at 12:33
  • Note that 512 bit keys are not secure anymore. You need 1024 bit at the very minimum to be considered secure. – Maarten Bodewes Aug 08 '15 at 11:48

1 Answers1

3

I figured out that the RSAPrivateKey api expects unsigned values and the toByteArray of a BigInteger returns the signed version. This post ( BigInteger to byte[] ) helped to figure me out I could simply remove the leading zero byte in the modulus byte array. It's working ok now.

Community
  • 1
  • 1
ChristopherS
  • 853
  • 4
  • 16
  • 1
    The API is underdefined on this spot. It says that the value should be "big endian" and "right aligned" but it doesn't explicitly specify that it should be unsigned (or not). In general the asymmetric coprocessors will only handle positive numbers though, so unsigned does make more sense. But in principle implementations *could* be incompatible if the API design is considered leading. – Maarten Bodewes Aug 08 '15 at 11:51