From b3262905bdb6df86e0d2c75ca96bb77d41f12a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Dvo=C5=99=C3=A1k?= Date: Thu, 7 Sep 2023 14:32:58 +0200 Subject: [PATCH] Fix #524: Include version in the token digest (#525) * Fix #524: Include version in the token digest * Include version decision making in the library * Improve the switch-case block a bit --- .../client/token/ClientTokenGenerator.java | 5 +++-- .../powerauth/crypto/lib/util/TokenUtils.java | 17 ++++++++++++----- .../server/token/ServerTokenVerifier.java | 5 +++-- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/client/token/ClientTokenGenerator.java b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/client/token/ClientTokenGenerator.java index a2227f6ed..581cbc031 100644 --- a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/client/token/ClientTokenGenerator.java +++ b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/client/token/ClientTokenGenerator.java @@ -55,13 +55,14 @@ public byte[] generateTokenTimestamp() { * * @param nonce Token nonce, 16 random bytes. * @param timestamp Token timestamp, Unix timestamp format encoded as bytes (from string representation). + * @param version Protocol version. * @param tokenSecret Token secret, 16 random bytes. * @return Token digest computed using provided data bytes with given token secret. * @throws GenericCryptoException In case digest computation fails. * @throws CryptoProviderException In case cryptography provider is incorrectly initialized. */ - public byte[] computeTokenDigest(byte[] nonce, byte[] timestamp, byte[] tokenSecret) throws GenericCryptoException, CryptoProviderException { - return tokenUtils.computeTokenDigest(nonce, timestamp, tokenSecret); + public byte[] computeTokenDigest(byte[] nonce, byte[] timestamp, String version, byte[] tokenSecret) throws GenericCryptoException, CryptoProviderException { + return tokenUtils.computeTokenDigest(nonce, timestamp, version, tokenSecret); } } diff --git a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/util/TokenUtils.java b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/util/TokenUtils.java index 9e53650a4..897f921fc 100644 --- a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/util/TokenUtils.java +++ b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/util/TokenUtils.java @@ -92,14 +92,20 @@ public byte[] convertTokenTimestamp(long timestamp) { * Compute the digest of provided token information using given token secret. * @param nonce Token nonce, 16 random bytes. * @param timestamp Token timestamp, Unix timestamp format encoded as bytes (string representation). + * @param version Protocol version. * @param tokenSecret Token secret, 16 random bytes. * @return Token digest computed using provided data bytes with given token secret. * @throws GenericCryptoException In case digest computation fails. * @throws CryptoProviderException In case cryptography provider is incorrectly initialized. */ - public byte[] computeTokenDigest(byte[] nonce, byte[] timestamp, byte[] tokenSecret) throws GenericCryptoException, CryptoProviderException { - byte[] amp = "&".getBytes(StandardCharsets.UTF_8); - byte[] data = ByteUtils.concat(nonce, amp, timestamp); + public byte[] computeTokenDigest(byte[] nonce, byte[] timestamp, String version, byte[] tokenSecret) throws GenericCryptoException, CryptoProviderException { + final byte[] amp = "&".getBytes(StandardCharsets.UTF_8); + final byte[] data; + switch (version) { + case "3.2" -> data = ByteUtils.concat(nonce, amp, timestamp, amp, version.getBytes(StandardCharsets.UTF_8)); + case "3.0", "3.1" -> data = ByteUtils.concat(nonce, amp, timestamp); + default -> throw new GenericCryptoException("Unsupported version value was specified: " + version); + } return hmac.hash(tokenSecret, data); } @@ -107,14 +113,15 @@ public byte[] computeTokenDigest(byte[] nonce, byte[] timestamp, byte[] tokenSec * Validate provided token digest for given input data and provided token secret. * @param nonce Token nonce, 16 random bytes. * @param timestamp Token timestamp, Unix timestamp format encoded as bytes (string representation). + * @param version Protocol version. * @param tokenSecret Token secret, 16 random bytes. * @param tokenDigest Token digest, 32 bytes to be validated. * @return Token digest computed using provided data bytes with given token secret. * @throws GenericCryptoException In case digest computation fails. * @throws CryptoProviderException In case cryptography provider is incorrectly initialized. */ - public boolean validateTokenDigest(byte[] nonce, byte[] timestamp, byte[] tokenSecret, byte[] tokenDigest) throws GenericCryptoException, CryptoProviderException { - return SideChannelUtils.constantTimeAreEqual(computeTokenDigest(nonce, timestamp, tokenSecret), tokenDigest); + public boolean validateTokenDigest(byte[] nonce, byte[] timestamp, String version, byte[] tokenSecret, byte[] tokenDigest) throws GenericCryptoException, CryptoProviderException { + return SideChannelUtils.constantTimeAreEqual(computeTokenDigest(nonce, timestamp, version, tokenSecret), tokenDigest); } } diff --git a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/server/token/ServerTokenVerifier.java b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/server/token/ServerTokenVerifier.java index 45c2187b0..5e65f9981 100644 --- a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/server/token/ServerTokenVerifier.java +++ b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/server/token/ServerTokenVerifier.java @@ -44,14 +44,15 @@ public byte[] convertTokenTimestamp(long timestamp) { * Validate provided token digest for given input data and provided token secret. * @param nonce Token nonce, 16 random bytes. * @param timestamp Token timestamp, Unix timestamp format encoded as bytes (from string representation). + * @param version Protocol version. * @param tokenSecret Token secret, 16 random bytes. * @param tokenDigest Token digest, 32 bytes to be validated. * @return Token digest computed using provided data bytes with given token secret. * @throws GenericCryptoException In case digest computation fails. * @throws CryptoProviderException In case cryptography provider is incorrectly initialized. */ - public boolean validateTokenDigest(byte[] nonce, byte[] timestamp, byte[] tokenSecret, byte[] tokenDigest) throws GenericCryptoException, CryptoProviderException { - return tokenUtils.validateTokenDigest(nonce, timestamp, tokenSecret, tokenDigest); + public boolean validateTokenDigest(byte[] nonce, byte[] timestamp, String version, byte[] tokenSecret, byte[] tokenDigest) throws GenericCryptoException, CryptoProviderException { + return tokenUtils.validateTokenDigest(nonce, timestamp, version, tokenSecret, tokenDigest); } }