diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/util/AcmeUtils.java b/acme4j-client/src/main/java/org/shredzone/acme4j/util/AcmeUtils.java index 45581c66..a8d38e02 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/util/AcmeUtils.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/util/AcmeUtils.java @@ -99,6 +99,17 @@ public final class AcmeUtils { return Base64Url.encode(data); } + /** + * Base64 decodes to a byte array, using URL style encoding. + * + * @param base64 + * base64 encoded string + * @return decoded data + */ + public static byte[] base64UrlDecode(String base64) { + return Base64Url.decode(base64); + } + /** * ASCII encodes a domain name. *

diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/util/JSON.java b/acme4j-client/src/main/java/org/shredzone/acme4j/util/JSON.java index f7fcffc5..a17be6ee 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/util/JSON.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/util/JSON.java @@ -393,6 +393,19 @@ public final class JSON implements Serializable { } } + /** + * Returns the value as base64 decoded byte array. + * + * @return byte array, or {@code null} if the value was not set. + */ + public byte[] asBinary() { + if (val == null) { + return null; + } + + return AcmeUtils.base64UrlDecode(val.toString()); + } + /** * Returns the parsed status. * diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/util/AcmeUtilsTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/util/AcmeUtilsTest.java index 46f92e19..2a1f24c6 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/util/AcmeUtilsTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/util/AcmeUtilsTest.java @@ -84,6 +84,15 @@ public class AcmeUtilsTest { assertThat(base64UrlEncode, is("w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI")); } + /** + * Test base64 URL decode. + */ + @Test + public void testBase64UrlDecode() { + byte[] base64UrlDecode = base64UrlDecode("w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI"); + assertThat(base64UrlDecode, is(sha256hash("foobar"))); + } + /** * Test ACE conversion. */ diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/util/JSONTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/util/JSONTest.java index 18d102e3..110f8e4b 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/util/JSONTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/util/JSONTest.java @@ -86,7 +86,7 @@ public class JSONTest { assertThat(json.keySet(), containsInAnyOrder( "text", "number", "boolean", "uri", "url", "date", "array", - "collect", "status")); + "collect", "status", "binary")); assertThat(json.contains("text"), is(true)); assertThat(json.contains("music"), is(false)); assertThat(json.get("text"), is(notNullValue())); @@ -181,6 +181,7 @@ public class JSONTest { assertThat(json.get("url").asURL(), is(new URL("http://example.com"))); assertThat(json.get("date").asInstant(), is(date)); assertThat(json.get("status").asStatusOrElse(Status.INVALID), is(Status.VALID)); + assertThat(json.get("binary").asBinary(), is("Chainsaw".getBytes())); JSON.Array array = json.get("array").asArray(); assertThat(array.get(0).asString(), is("foo")); @@ -209,6 +210,7 @@ public class JSONTest { assertThat(json.get("none").asInstant(), is(nullValue())); assertThat(json.get("none").asObject(), is(nullValue())); assertThat(json.get("none").asStatusOrElse(Status.INVALID), is(Status.INVALID)); + assertThat(json.get("none").asBinary(), is(nullValue())); try { json.get("none").asInt(); diff --git a/acme4j-client/src/test/resources/json.properties b/acme4j-client/src/test/resources/json.properties index c0a89b7d..cde9df9c 100644 --- a/acme4j-client/src/test/resources/json.properties +++ b/acme4j-client/src/test/resources/json.properties @@ -45,7 +45,8 @@ json = \ "date": "2016-01-08T00:00:00Z",\ "array": ["foo", 987, [1, 2, 3], {"test": "ok"}],\ "collect": ["foo", "bar", "barfoo"],\ - "status": "VALID"\ + "status": "VALID",\ + "binary": "Q2hhaW5zYXc"\ } newRegistration = \