Vonage / vonage-java-sdk

Vonage Server SDK for Java. API support for SMS, Messages, Voice, Text-to-Speech, Numbers, Verify (2FA), Video and more.
https://developer.vonage.com/en/home
Apache License 2.0
96 stars 121 forks source link

new JWTAuthMethod throws java.security.InvalidKeyException: Private key should be provided in PEM format! #39

Closed leggetter closed 7 years ago

leggetter commented 7 years ago

Steps to reproduce:

  1. create a new application using the Nexmo CLI
  2. Execute code: new JWTAuthMethod(applicationId, pathToPrivateKey);

Digging a bit deeper there seems to be something potentially going on with the contents of the file as stored by the CLI. If you output it to stdout then it looks fine. If you copy and past the content into a string the PEM regexp works fine. But reading directly from the file and running the regexp against it fails.

Here's a basic example of a test for this after digging in to the code for JWTAuthMethod:

            Pattern pemPattern = Pattern.compile("-----BEGIN PRIVATE KEY-----.*-----END PRIVATE KEY-----", Pattern.MULTILINE | Pattern.DOTALL);

            Path path = Paths.get("private.key");
            byte[] privateKey = Files.readAllBytes(path);
            String s = new String(privateKey, StandardCharsets.UTF_8);
            System.out.println(s);

            StringBuilder sb = new StringBuilder("-----BEGIN PRIVATE KEY-----\n" +
                    "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC/5SukrAilz/F4\n" +
                    "/0KBTFQD47ErblpgjxtfLPc=\n" +
                    "-----END PRIVATE KEY-----");

            Matcher fileExtracter = pemPattern.matcher(s);
            Matcher hardCodedExtracter = pemPattern.matcher(sb.toString());

            System.out.println("fileExtracter.matches(): " + fileExtracter.matches());
            System.out.println("hardCodedExtracter.matches(): " + hardCodedExtracter.matches());

Where the output is:

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC/5SukrAilz/F4
/0KBTFQD47ErblpgjxtfLPc=
-----END PRIVATE KEY-----

fileExtracter.matches(): false
hardCodedExtracter.matches(): true
judy2k commented 7 years ago

FYI, my pem file predates the flag for the CLI to save the key to file. So my file will have been created by copy/pasting from the console into a file. I don't know if this makes any difference, but... maybe.

judy2k commented 7 years ago

@leggetter Could you change the regex so that it has \\n? at the end to catch a trailing newline, if there is one?

leggetter commented 7 years ago

@judy2k Changing the regex doesn't make any difference. I event tried just BEGIN as the regex. There's some kind of fundamental problem in reading the file and converting it to a String. Let's look at this outside of the weekend :)

leggetter commented 7 years ago

With the regex of:

"-----BEGIN PRIVATE KEY-----\\n(.*\\n)-----END PRIVATE KEY-----", Pattern.MULTILINE | Pattern.DOTALL

The output is:

fileExtracter.matches(): false
hardCodedExtracter.matches(): true
leggetter commented 7 years ago

Some test code for this available via https://github.com/nexmo-community/nexmo-java-quickstart/blob/master/src/main/java/App.java

judy2k commented 7 years ago

This was due to a trailing line break at the end of the PEM file, and the regex for extracting the key data being to strict. I've fixed and am publishing a new SNAPSHOT release.

judy2k commented 7 years ago

@leggetter Could you check the new SNAPSHOT release against your test? You may want to use one of the techniques in this slide to make sure the new release is downloaded.

leggetter commented 7 years ago

Looks to be resolved. I'm now at #40