diff --git a/NOTICE b/NOTICE
index d8ee885..734ee8b 100644
--- a/NOTICE
+++ b/NOTICE
@@ -19,6 +19,7 @@ This project includes:
ASM Tree under BSD
ASM Util under BSD
Gson under Apache 2.0
+ HKDF-RFC5869 under Apache License, Version 2.0
jffi under The Apache Software License, Version 2.0
jnr-a64asm under The Apache Software License, Version 2.0
jnr-ffi under The Apache Software License, Version 2.0
diff --git a/README.md b/README.md
index 129fca5..821a86d 100644
--- a/README.md
+++ b/README.md
@@ -202,18 +202,18 @@ If you're building a (non-Android) JDK project, you will want to define the foll
dev.paseto
jpaseto-api
- 0.1.0
+ 0.5.0
dev.paseto
jpaseto-impl
- 0.1.0
+ 0.5.0
runtime
dev.paseto
jpaseto-jackson
- 0.1.0
+ 0.5.0
runtime
@@ -221,7 +221,15 @@ If you're building a (non-Android) JDK project, you will want to define the foll
dev.paseto
jpaseto-bouncy-castle
- 0.1.0
+ 0.5.0
+ runtime
+ -->
+
+
@@ -230,7 +238,7 @@ If you're building a (non-Android) JDK project, you will want to define the foll
dev.paseto
jpaseto-sodium
- 0.1.0
+ 0.5.0
runtime
-->
```
@@ -240,14 +248,16 @@ If you're building a (non-Android) JDK project, you will want to define the foll
```groovy
dependencies {
- compile 'dev.paseto:jpaseto-api:0.1.0'
- runtime 'dev.paseto:jpaseto-impl:0.1.0',
+ compile 'dev.paseto:jpaseto-api:0.5.0'
+ runtime 'dev.paseto:jpaseto-impl:0.5.0',
// Uncomment the next lines if you want to use v1.local tokens
- // 'dev.paseto:jpaseto-bouncy-castle:0.1.0',
+ // 'dev.paseto:jpaseto-bouncy-castle:0.5.0',
+ // or this (only 'v1.local' tokens) for smaller dependency (~11 KB for HKDF vs. ~4.3 MB for Bouncy Castle)
+ // 'dev.paseto:jpaseto-hkdf:0.5.0',
// Uncomment the next lines if you want to use v2 tokens
// NOTE: this requires the native lib sodium library installed on your system see below
- // 'dev.paseto:jpaseto-sodium:0.1.0',
- 'dev.paseto:jpaseto-jackson:0.1.0'
+ // 'dev.paseto:jpaseto-sodium:0.5.0',
+ 'dev.paseto:jpaseto-jackson:0.5.0'
}
```
@@ -255,7 +265,7 @@ dependencies {
Installation the a native library [libsodium](https://github.com/jedisct1/libsodium) is required when creating or parseing "v2.local" tokens.
-**NOTE:** `public` tokens can be used with the `jpaseto-bouncy-castle` dependency or Java 11+. `v1.local` tokens require `jpaseto-bouncy-castle`.
+**NOTE:** `public` tokens can be used with the `jpaseto-bouncy-castle` dependency or Java 11+. `v1.local` tokens require `jpaseto-bouncy-castle` or `jpaseto-hkdf`.
- MacOS - Can install libsodium using brew:
diff --git a/api/pom.xml b/api/pom.xml
index 91fc0e2..7ce769d 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -20,7 +20,7 @@
dev.paseto
jpaseto-root
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
jpaseto-api
diff --git a/coverage/pom.xml b/coverage/pom.xml
index 0f0e83c..eefbbcc 100644
--- a/coverage/pom.xml
+++ b/coverage/pom.xml
@@ -21,7 +21,7 @@
dev.paseto
jpaseto-root
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
jpaseto-coverage
@@ -49,6 +49,10 @@
dev.paseto
jpaseto-bouncy-castle
+
+ dev.paseto
+ jpaseto-hkdf
+
dev.paseto
jpaseto-its-sodium-jackson
diff --git a/extensions/crypto/bouncy-castle/pom.xml b/extensions/crypto/bouncy-castle/pom.xml
index fca44e8..479020c 100644
--- a/extensions/crypto/bouncy-castle/pom.xml
+++ b/extensions/crypto/bouncy-castle/pom.xml
@@ -20,7 +20,7 @@
dev.paseto
jpaseto-root
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
../../../pom.xml
diff --git a/extensions/crypto/bouncy-castle/src/main/java/dev/paseto/jpaseto/crypto/bouncycastle/BouncyCastleV1LocalCryptoProvider.java b/extensions/crypto/bouncy-castle/src/main/java/dev/paseto/jpaseto/crypto/bouncycastle/BouncyCastleV1LocalCryptoProvider.java
index bcc90c6..596fd31 100644
--- a/extensions/crypto/bouncy-castle/src/main/java/dev/paseto/jpaseto/crypto/bouncycastle/BouncyCastleV1LocalCryptoProvider.java
+++ b/extensions/crypto/bouncy-castle/src/main/java/dev/paseto/jpaseto/crypto/bouncycastle/BouncyCastleV1LocalCryptoProvider.java
@@ -16,93 +16,23 @@
package dev.paseto.jpaseto.crypto.bouncycastle;
import com.google.auto.service.AutoService;
-import dev.paseto.jpaseto.InvalidMacException;
-import dev.paseto.jpaseto.impl.crypto.Hmacs;
-import dev.paseto.jpaseto.impl.crypto.PreAuthEncoder;
+import dev.paseto.jpaseto.impl.crypto.BaseV1LocalCryptoProvider;
import dev.paseto.jpaseto.impl.crypto.V1LocalCryptoProvider;
-import dev.paseto.jpaseto.impl.lang.Bytes;
import org.bouncycastle.crypto.generators.HKDFBytesGenerator;
import org.bouncycastle.crypto.params.HKDFParameters;
import org.bouncycastle.crypto.util.DigestFactory;
-import javax.crypto.Cipher;
import javax.crypto.SecretKey;
-import java.security.MessageDigest;
-import java.util.Arrays;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
@AutoService(V1LocalCryptoProvider.class)
-public class BouncyCastleV1LocalCryptoProvider implements V1LocalCryptoProvider {
-
- private static final byte[] HEADER_BYTES = "v1.local.".getBytes(UTF_8);
+public class BouncyCastleV1LocalCryptoProvider extends BaseV1LocalCryptoProvider {
@Override
- public byte[] encrypt(byte[] payload, byte[] footer, byte[] nonce, SecretKey sharedSecret) {
-
- byte[] salt = Arrays.copyOf(nonce, 16);
- byte[] rightNonce = Arrays.copyOfRange(nonce, 16, nonce.length);
-
- // 4
- byte[] encryptionKey = encryptionKey(sharedSecret, salt);
- byte[] authenticationKey = authenticationKey(sharedSecret, salt);
-
- // 5
- byte[] cipherText = V1LocalCryptoProvider.doCipher(Cipher.ENCRYPT_MODE, encryptionKey, rightNonce, payload);
-
- //6
- byte[] preAuth = PreAuthEncoder.encode(HEADER_BYTES, nonce, cipherText, footer);
-
- //7
- byte[] calculatedMac = Hmacs.hmacSha384(authenticationKey, preAuth);
-
- // 8
- return Bytes.concat(nonce, cipherText, calculatedMac);
- }
-
- @Override
- public byte[] decrypt(byte[] encryptedBytes, byte[] footer, byte[] nonce, SecretKey sharedSecret) {
-
- // 3
- byte[] salt = Arrays.copyOf(nonce, 16);
- byte[] rightNonce = Arrays.copyOfRange(nonce, 16, nonce.length);
-
- byte[] cipherText = Arrays.copyOfRange(encryptedBytes, 32, encryptedBytes.length - 48);
- byte[] mac = Arrays.copyOfRange(encryptedBytes, encryptedBytes.length - 48, encryptedBytes.length);
-
- // 4
- byte[] encryptionKey = encryptionKey(sharedSecret, salt);
- byte[] authenticationKey = authenticationKey(sharedSecret, salt);
-
- // 5
- byte[] preAuth = PreAuthEncoder.encode(HEADER_BYTES, nonce, cipherText, footer);
-
- // 6
- byte[] calculatedMac = Hmacs.hmacSha384(authenticationKey, preAuth);
-
- // 7
- if (!MessageDigest.isEqual(calculatedMac, mac)) {
- throw new InvalidMacException("Failed to validate mac in token");
- }
-
- // 8
- return V1LocalCryptoProvider.doCipher(Cipher.DECRYPT_MODE, encryptionKey, rightNonce, cipherText);
- }
-
- private byte[] hkdfSha384(SecretKey sharedSecret, byte[] salt, String info) {
-
+ protected byte[] hkdfSha384(SecretKey sharedSecret, byte[] salt, byte[] info) {
HKDFBytesGenerator hkdfBytesGenerator = new HKDFBytesGenerator(DigestFactory.createSHA384());
- hkdfBytesGenerator.init(new HKDFParameters(sharedSecret.getEncoded(), salt, info.getBytes(UTF_8)));
+ hkdfBytesGenerator.init(new HKDFParameters(sharedSecret.getEncoded(), salt, info));
byte[] result = new byte[32];
hkdfBytesGenerator.generateBytes(result, 0, result.length);
return result;
}
-
- private byte[] encryptionKey(SecretKey sharedSecret, byte[] salt) {
- return hkdfSha384(sharedSecret, salt, "paseto-encryption-key");
- }
-
- private byte[] authenticationKey(SecretKey sharedSecret, byte[] salt) {
- return hkdfSha384(sharedSecret, salt, "paseto-auth-key-for-aead");
- }
}
diff --git a/extensions/crypto/bouncy-castle/src/test/groovy/dev/paseto/jpaseto/crypto/bouncycastle/BouncyCastleV1LocalCryptoProviderTest.groovy b/extensions/crypto/bouncy-castle/src/test/groovy/dev/paseto/jpaseto/crypto/bouncycastle/BouncyCastleV1LocalCryptoProviderTest.groovy
new file mode 100644
index 0000000..d920389
--- /dev/null
+++ b/extensions/crypto/bouncy-castle/src/test/groovy/dev/paseto/jpaseto/crypto/bouncycastle/BouncyCastleV1LocalCryptoProviderTest.groovy
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2020-Present paseto.dev
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dev.paseto.jpaseto.crypto.bouncycastle
+
+import dev.paseto.jpaseto.impl.crypto.V1LocalCryptoProvider
+import dev.paseto.jpaseto.lang.Keys
+import dev.paseto.jpaseto.lang.Services
+import org.testng.annotations.Test
+
+import javax.crypto.SecretKey
+import java.nio.charset.StandardCharsets
+
+import static org.hamcrest.MatcherAssert.assertThat
+import static org.hamcrest.Matchers.equalTo
+import static org.hamcrest.Matchers.instanceOf
+class BouncyCastleV1LocalCryptoProviderTest {
+
+ @Test
+ void loadServiceTest() {
+ assertThat Services.loadFirst(V1LocalCryptoProvider), instanceOf(BouncyCastleV1LocalCryptoProvider)
+ }
+
+ @Test
+ void hkdfSha384Test() {
+ SecretKey secretKey = Keys.secretKey(decode("3nQBDXcLZRTcVZF0NS/6yZ3JO03i/Yv+C1CQRvPgmJk"))
+ byte[] salt = decode("/bvrxpG04bMH2j98Sgm5ug")
+ byte[] info = "test-info".getBytes(StandardCharsets.UTF_8)
+ String expectedResult = "PtiIWzWkNywvjlnyv60Rtz2Zr7vQsgZivlj0Ys9HDy4"
+
+ byte[] result = new BouncyCastleV1LocalCryptoProvider().hkdfSha384(secretKey, salt, info)
+ assertThat encodeToString(result), equalTo(expectedResult)
+ }
+
+ private static String encodeToString(byte[] bytes) {
+ return Base64.getEncoder().withoutPadding().encodeToString(bytes)
+ }
+
+ private static byte[] decode(String input) {
+ return Base64.getDecoder().decode(input)
+ }
+}
diff --git a/extensions/crypto/hkdf/pom.xml b/extensions/crypto/hkdf/pom.xml
new file mode 100644
index 0000000..26d25c5
--- /dev/null
+++ b/extensions/crypto/hkdf/pom.xml
@@ -0,0 +1,49 @@
+
+
+
+ 4.0.0
+
+
+ dev.paseto
+ jpaseto-root
+ 0.5.0-SNAPSHOT
+ ../../../pom.xml
+
+
+ jpaseto-hkdf
+ JPaseto :: Crypto :: HKDF
+
+
+
+ dev.paseto
+ jpaseto-impl
+
+
+
+ at.favre.lib
+ hkdf
+
+
+
+ com.google.auto.service
+ auto-service
+ provided
+ true
+
+
+
+
\ No newline at end of file
diff --git a/extensions/crypto/hkdf/src/main/java/dev/paseto/jpaseto/crypto/hkdf/HKDFV1LocalCryptoProvider.java b/extensions/crypto/hkdf/src/main/java/dev/paseto/jpaseto/crypto/hkdf/HKDFV1LocalCryptoProvider.java
new file mode 100644
index 0000000..fc34fa3
--- /dev/null
+++ b/extensions/crypto/hkdf/src/main/java/dev/paseto/jpaseto/crypto/hkdf/HKDFV1LocalCryptoProvider.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2020-Present paseto.dev
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dev.paseto.jpaseto.crypto.hkdf;
+
+import at.favre.lib.crypto.HKDF;
+import at.favre.lib.crypto.HkdfMacFactory;
+import com.google.auto.service.AutoService;
+import dev.paseto.jpaseto.impl.crypto.BaseV1LocalCryptoProvider;
+import dev.paseto.jpaseto.impl.crypto.V1LocalCryptoProvider;
+
+import javax.crypto.SecretKey;
+
+/**
+ * @since 0.5.0
+ */
+@AutoService(V1LocalCryptoProvider.class)
+public class HKDFV1LocalCryptoProvider extends BaseV1LocalCryptoProvider {
+
+ @Override
+ protected byte[] hkdfSha384(SecretKey sharedSecret, byte[] salt, byte[] info) {
+ HKDF hkdfSha384 = HKDF.from(new HkdfMacFactory.Default("HmacSHA384"));
+ return hkdfSha384.extractAndExpand(salt, sharedSecret.getEncoded(), info, 32);
+ }
+}
diff --git a/extensions/crypto/hkdf/src/test/groovy/dev/paseto/jpaseto/crypto/hkdf/HKDFV1LocalCryptoProviderTest.groovy b/extensions/crypto/hkdf/src/test/groovy/dev/paseto/jpaseto/crypto/hkdf/HKDFV1LocalCryptoProviderTest.groovy
new file mode 100644
index 0000000..510b146
--- /dev/null
+++ b/extensions/crypto/hkdf/src/test/groovy/dev/paseto/jpaseto/crypto/hkdf/HKDFV1LocalCryptoProviderTest.groovy
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2020-Present paseto.dev
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dev.paseto.jpaseto.crypto.hkdf
+
+import dev.paseto.jpaseto.impl.crypto.V1LocalCryptoProvider
+import dev.paseto.jpaseto.lang.Keys
+import dev.paseto.jpaseto.lang.Services
+import org.testng.annotations.Test
+
+import javax.crypto.SecretKey
+import java.nio.charset.StandardCharsets
+
+import static org.hamcrest.MatcherAssert.assertThat
+import static org.hamcrest.Matchers.equalTo
+import static org.hamcrest.Matchers.instanceOf
+
+class HKDFV1LocalCryptoProviderTest {
+
+ @Test
+ void loadServiceTest() {
+ assertThat Services.loadFirst(V1LocalCryptoProvider), instanceOf(HKDFV1LocalCryptoProvider)
+ }
+
+ @Test
+ void hkdfSha384Test() {
+ SecretKey secretKey = Keys.secretKey(decode("3nQBDXcLZRTcVZF0NS/6yZ3JO03i/Yv+C1CQRvPgmJk"))
+ byte[] salt = decode("/bvrxpG04bMH2j98Sgm5ug")
+ byte[] info = "test-info".getBytes(StandardCharsets.UTF_8)
+ String expectedResult = "PtiIWzWkNywvjlnyv60Rtz2Zr7vQsgZivlj0Ys9HDy4"
+
+ byte[] result = new HKDFV1LocalCryptoProvider().hkdfSha384(secretKey, salt, info)
+ assertThat encodeToString(result), equalTo(expectedResult)
+ }
+
+ private static String encodeToString(byte[] bytes) {
+ return Base64.getEncoder().withoutPadding().encodeToString(bytes)
+ }
+
+ private static byte[] decode(String input) {
+ return Base64.getDecoder().decode(input)
+ }
+}
diff --git a/extensions/crypto/sodium/pom.xml b/extensions/crypto/sodium/pom.xml
index 309fd1b..4e1458e 100644
--- a/extensions/crypto/sodium/pom.xml
+++ b/extensions/crypto/sodium/pom.xml
@@ -20,7 +20,7 @@
dev.paseto
jpaseto-root
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
../../../pom.xml
diff --git a/extensions/json/gson/pom.xml b/extensions/json/gson/pom.xml
index 58410c3..453163d 100644
--- a/extensions/json/gson/pom.xml
+++ b/extensions/json/gson/pom.xml
@@ -21,7 +21,7 @@
dev.paseto
jpaseto-root
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
../../../pom.xml
diff --git a/extensions/json/jackson/pom.xml b/extensions/json/jackson/pom.xml
index 9f34747..83d5ee4 100644
--- a/extensions/json/jackson/pom.xml
+++ b/extensions/json/jackson/pom.xml
@@ -20,7 +20,7 @@
dev.paseto
jpaseto-root
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
../../../pom.xml
diff --git a/impl/pom.xml b/impl/pom.xml
index cf53455..af3678c 100644
--- a/impl/pom.xml
+++ b/impl/pom.xml
@@ -20,7 +20,7 @@
dev.paseto
jpaseto-root
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
jpaseto-impl
diff --git a/impl/src/main/java/dev/paseto/jpaseto/impl/crypto/BaseV1LocalCryptoProvider.java b/impl/src/main/java/dev/paseto/jpaseto/impl/crypto/BaseV1LocalCryptoProvider.java
new file mode 100644
index 0000000..2ed5cf5
--- /dev/null
+++ b/impl/src/main/java/dev/paseto/jpaseto/impl/crypto/BaseV1LocalCryptoProvider.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2019-Present paseto.dev
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dev.paseto.jpaseto.impl.crypto;
+
+import dev.paseto.jpaseto.InvalidMacException;
+import dev.paseto.jpaseto.impl.lang.Bytes;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import java.security.MessageDigest;
+import java.util.Arrays;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+public abstract class BaseV1LocalCryptoProvider implements V1LocalCryptoProvider {
+
+ private static final byte[] HEADER_BYTES = "v1.local.".getBytes(UTF_8);
+
+ @Override
+ public byte[] encrypt(byte[] payload, byte[] footer, byte[] nonce, SecretKey sharedSecret) {
+
+ byte[] salt = Arrays.copyOf(nonce, 16);
+ byte[] rightNonce = Arrays.copyOfRange(nonce, 16, nonce.length);
+
+ // 4
+ byte[] encryptionKey = encryptionKey(sharedSecret, salt);
+ byte[] authenticationKey = authenticationKey(sharedSecret, salt);
+
+ // 5
+ byte[] cipherText = V1LocalCryptoProvider.doCipher(Cipher.ENCRYPT_MODE, encryptionKey, rightNonce, payload);
+
+ //6
+ byte[] preAuth = PreAuthEncoder.encode(HEADER_BYTES, nonce, cipherText, footer);
+
+ //7
+ byte[] calculatedMac = Hmacs.hmacSha384(authenticationKey, preAuth);
+
+ // 8
+ return Bytes.concat(nonce, cipherText, calculatedMac);
+ }
+
+ @Override
+ public byte[] decrypt(byte[] encryptedBytes, byte[] footer, byte[] nonce, SecretKey sharedSecret) {
+
+ // 3
+ byte[] salt = Arrays.copyOf(nonce, 16);
+ byte[] rightNonce = Arrays.copyOfRange(nonce, 16, nonce.length);
+
+ byte[] cipherText = Arrays.copyOfRange(encryptedBytes, 32, encryptedBytes.length - 48);
+ byte[] mac = Arrays.copyOfRange(encryptedBytes, encryptedBytes.length - 48, encryptedBytes.length);
+
+ // 4
+ byte[] encryptionKey = encryptionKey(sharedSecret, salt);
+ byte[] authenticationKey = authenticationKey(sharedSecret, salt);
+
+ // 5
+ byte[] preAuth = PreAuthEncoder.encode(HEADER_BYTES, nonce, cipherText, footer);
+
+ // 6
+ byte[] calculatedMac = Hmacs.hmacSha384(authenticationKey, preAuth);
+
+ // 7
+ if (!MessageDigest.isEqual(calculatedMac, mac)) {
+ throw new InvalidMacException("Failed to validate mac in token");
+ }
+
+ // 8
+ return V1LocalCryptoProvider.doCipher(Cipher.DECRYPT_MODE, encryptionKey, rightNonce, cipherText);
+ }
+
+ private byte[] encryptionKey(SecretKey sharedSecret, byte[] salt) {
+ return hkdfSha384(sharedSecret, salt, "paseto-encryption-key");
+ }
+
+ private byte[] authenticationKey(SecretKey sharedSecret, byte[] salt) {
+ return hkdfSha384(sharedSecret, salt, "paseto-auth-key-for-aead");
+ }
+
+ private byte[] hkdfSha384(SecretKey sharedSecret, byte[] salt, String info) {
+ return hkdfSha384(sharedSecret, salt, info.getBytes(UTF_8));
+ }
+
+ protected abstract byte[] hkdfSha384(SecretKey sharedSecret, byte[] salt, byte[] info);
+}
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 8325933..5e9c603 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -20,7 +20,7 @@
dev.paseto
jpaseto-root
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
jpaseto-its-sodium-jackson
@@ -46,6 +46,11 @@
jpaseto-bouncy-castle
runtime
+
+ dev.paseto
+ jpaseto-hkdf
+ runtime
+
dev.paseto
jpaseto-jackson
diff --git a/pom.xml b/pom.xml
index b1db0f7..7db523c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,7 +25,7 @@
dev.paseto
jpaseto-root
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
pom
JPaseto
@@ -68,6 +68,7 @@
impl
extensions/crypto/sodium
extensions/crypto/bouncy-castle
+ extensions/crypto/hkdf
extensions/json/jackson
extensions/json/gson
integration-tests
@@ -79,33 +80,38 @@
dev.paseto
jpaseto-api
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
dev.paseto
jpaseto-impl
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
dev.paseto
jpaseto-jackson
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
dev.paseto
jpaseto-sodium
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
dev.paseto
jpaseto-bouncy-castle
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
+
+
+ dev.paseto
+ jpaseto-hkdf
+ 0.5.0-SNAPSHOT
dev.paseto
jpaseto-its-sodium-jackson
test
- 0.4.1-SNAPSHOT
+ 0.5.0-SNAPSHOT
@@ -120,6 +126,12 @@
1.64
+
+ at.favre.lib
+ hkdf
+ 1.1.0
+
+