3

I created public.der and private.der using openssl. I need to hard code the generated public key into code rather than reading that key from public.der file. When I read key from file into byte[] and printing that byte array gives me output like "[B@74a14482". I can run program by reading key from file but it is taking time for execution so I want to hard code key directly into program. I have the following function

public PublicKey readPublicKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, URISyntaxException {
    String str = "[B@74a14482";
    byte[] b = str.getBytes();
    X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(b);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");

    return keyFactory.generatePublic(publicSpec);
}

but it is giving me error as

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: Detect premature EOF

I referred to this and run but I got the same error.

Code which prints the byte array:

public byte[] readFileBytes(String filename) throws IOException, URISyntaxException {

    return ByteStreams.toByteArray(ResourceLoader.loadFile(filename));
}

public PublicKey readPublicKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, URISyntaxException {
    System.out.println(readFileBytes(filename));
    String str = "[B@74a14482";

    byte[] keyBytes;
    keyBytes = (new BASE64Decoder()).decodeBuffer(str);
    X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");

    return keyFactory.generatePublic(publicSpec);
}

Can you please help me with this. Where I m going wrong.

Benoit
  • 5,118
  • 2
  • 24
  • 43
Maddy8381
  • 406
  • 9
  • 20

2 Answers2

3

As pointed by @michalk, what you print is the result of the toString() method applied on the byte array. This method does not print the content of the array.

Another problem is that not all bytes can be converted to printable characters.

I would recommend to encore the key with Base64, this will give you a printable version of your key. Then you can decode this String it before using it.

To print the content of the file

byte [] keyBytes = readFileBytes(filename);
String keyString = Base64.getEncoder().encodeToString(key);
System.out.println(keyString);

To decode the key from a String

byte[] keyBytes = Base64.getDecoder().decode(keyString);

(instead of keyBytes = (new BASE64Decoder()).decodeBuffer(str);)

Benoit
  • 5,118
  • 2
  • 24
  • 43
2

System.out.println() of a byte[] prints only the hashcode of the object not the contents; dupe What's the simplest way to print a Java array? and many other lower-rated or closed Qs. Also the hashcode is not even remotely similar to base64 so trying to decode it as base64 is entirely useless.

An RSA key encoding will be much larger. Here for example is one of my test RSA keys expressed as a valid initializer for a byte[] variable:

{48, -126, 1, 34, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -126, 1, 15, 0, 48, -126, 1, 10, 2, -126, 1, 1, 0, -79, -123, 63, 50, -126, 49, 97, -27, 110, 8, 87, 43, 95, -25, -60, 31, -107, -41, -2, 23, -65, -100, -108, -46, 67, -93, -8, 68, 93, -4, 12, -94, -51, -100, -37, 80, -11, 119, -25, 104, -63, 15, -109, 97, 23, -127, 34, 7, -109, -27, 87, -124, 79, 111, 100, -36, 108, 87, -79, 38, -114, 14, -126, -7, -28, 113, 80, 29, 77, 12, 27, 86, 25, 127, -45, -77, 103, 14, 96, 63, 25, -123, 43, -90, -124, -22, 101, 40, -95, 38, 116, 73, 51, 25, 79, -47, 122, 109, -26, -55, -16, 118, 5, 7, -115, -23, 20, -111, 22, 40, 25, 126, -60, 118, 35, -118, 26, 67, -106, 3, 88, -99, -18, -109, -94, 49, -47, 115, 120, -51, 12, 38, -73, 13, 109, -11, 111, 109, -128, 54, 64, 76, 50, -42, -45, -17, 46, 83, 77, -106, 115, 97, -21, 33, -52, -114, -68, 58, -119, 13, 124, -1, 93, 86, 62, 23, -22, 100, -81, 11, 63, -54, 3, -95, -58, -43, 93, 53, -114, -21, -34, 103, -110, 42, 52, -108, 86, 67, -94, 92, -57, 90, -88, -81, -74, -46, 95, -40, -82, -6, 25, 69, 87, -70, 28, 66, 19, -90, -17, 109, -1, 30, -104, 13, -86, 19, 78, 27, 27, -90, -40, -28, 0, -96, 88, -91, 33, -74, 81, -27, -55, -98, 116, 12, -56, -96, -10, 25, 61, -50, -69, 40, -82, -90, -2, -27, 62, -117, -17, 45, -106, 98, -87, -11, 72, 89, 2, 3, 1, 0, 1}

Because of the way Java/JVM initializes arrays, especially larger ones, this is pretty likely to be slow, which you say (only) in a comment is your actual concern. (This differs from C and C++, where at least static-duration initialized arrays are normally handled by the compiler and simply read -- or often mapped -- by the system loader.) In my experience reading a file with actual Java is fast, as long as the file is a real and local file, but I don't know what your 'ResourceLoader' is doing.

You might get better results by doing as most people do and use base64. Base64 is text consisting of characters suitable for handling in a String, unlike the arbitrary binary data in DER, and string constants are optimized in a Java class file, especially in j9 up where an ASCII-only constant can remain 1-byte in the String (although the base64 decoder may still expand to 2-byte). Add: upon submitting I see Benoit has already supplied the base64 implementation.

dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70