0

I am trying to sign a string message using a private key that I had generated using the commands from here. This is the piece of code below that I use to load and sign the message.

private String signMessage(String message) throws Exception {
    Signature rsa = Signature.getInstance("SHA1withRSA");
    rsa.initSign(getPrivate(privateKeyPath));
    rsa.update(message.getBytes());
    return rsa.sign().toString();
}

public PrivateKey getPrivate(String filename) throws Exception {
    byte[] keyBytes = Files.readAllBytes(new File(filename).toPath());
    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePrivate(spec);
}

To clarify the privatekeyPath I am supplying is similar to /path/test.der.

However, I am getting the following error when trying to sign the message - java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format

What is wrong here? Why cant I seem to sign a message with the private key? Can someone specify a working way to get this done?

Community
  • 1
  • 1
Killer Beast
  • 469
  • 6
  • 21
  • You have as well other issue, `rsa.sign().toString();` will return an array reference, not any signature. you need to encode the result to get a valid string (https://stackoverflow.com/questions/13109588/encoding-as-base64-in-java/13109632#13109632) – gusto2 Jul 06 '19 at 19:33
  • You may try to decode the private key content if it is bas64 encoded – gusto2 Jul 06 '19 at 19:39
  • A `der` file contains a certificate,not a private key. Usually you need a `.key` file or a `.pem` file whose content starts with `-----BEGIN PRIVATE KEY----` – pedrofb Jul 07 '19 at 10:58
  • tried with `.pem` as well. It says same error. I did cat `test.pem` and it shows a begin private key like you said – Killer Beast Jul 07 '19 at 14:31
  • can someone post a link with working signature creation and verification using a key file and how to generate that key file? – Killer Beast Jul 07 '19 at 15:01
  • 1
    I'm sorry I misread your question and confused `der` with `cer`. A der file can contain certificates or private keys in binary. In the case of pem files they are encoded in base 64. See a full example here https://stackoverflow.com/questions/11410770/load-rsa-public-key-from-file – pedrofb Jul 07 '19 at 16:15
  • works like a charm. Please post this as answer and will be glad to accept. – Killer Beast Jul 08 '19 at 13:10
  • 1
    It seems that your getPrivate method is correct, so I guess the problem was in the generation of the private key or in the format. Is it like that? – pedrofb Jul 09 '19 at 08:54
  • yes true. i followed that link and works fine – Killer Beast Jul 09 '19 at 09:08
  • @pedrofb just a quick question, verify method has 2 params - one the message and other saying signature. what should the 2nd param be? like is it the public key in base64 format? – Killer Beast Jul 10 '19 at 06:12
  • 1
    `Signature.verify(signature[])` has only one param. The message is set with `Signature.update(message[])` and the public key with `Signature.initVerify(pubKey)` – pedrofb Jul 10 '19 at 06:34
  • Not if you look at the question, it has something like this `public boolean verify(String message, String signature)`. Here first param is the signed message right? And what would be the 2nd param is my question? – Killer Beast Jul 10 '19 at 06:56
  • 1
    Okay, I did not understand you. The second parameter is the signature. In your question it would be the result of `rsa.sign()`. Note that in the linked question, the signature is encoded in base64. You do not need to do this because you can use the binary array. In your code `rsa.sign().toString()` is an error because a binary array can not be converted to a string. You should use the binary data or encode it to base 64 – pedrofb Jul 10 '19 at 07:02

1 Answers1

1

It seems that your getPrivate method is correct, so I think the problem is in the generation of the key or in the format

A der file can contain certificates or private keys in binary. In the case of pem files they are encoded in base 64. Usually you need a .key file or a .pem file whose content starts with -----BEGIN PRIVATE KEY-----

Make sure you're using a binary der format containing a pkcs#8 key so Java can read it. See a full example here: https://stackoverflow.com/a/19387517/6371459


In your code rsa.sign().toString() is an error because a binary array can not be converted to a string. You should use the binary data or encode it to base 64 Note that in the linked question the signature is encoded in base64. You do not need to do this because you can use the binary array.

pedrofb
  • 37,271
  • 5
  • 94
  • 142