diff --git a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/EncryptorFactory.java b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/EncryptorFactory.java index 949deabe5..de00d7534 100644 --- a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/EncryptorFactory.java +++ b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/EncryptorFactory.java @@ -62,7 +62,7 @@ public ClientEncryptor getClientEncryptor(EncryptorId encryptorId, EncryptorPara validateParameters(encryptorId, encryptorParameters); final ClientEncryptor encryptor; switch (encryptorParameters.getProtocolVersion()) { - case "3.2", "3.1", "3.0" -> { + case "3.3", "3.2", "3.1", "3.0" -> { encryptor = new ClientEciesEncryptor(encryptorId, encryptorParameters); } default -> { @@ -106,7 +106,7 @@ public ServerEncryptor getServerEncryptor(EncryptorId encryptorId, EncryptorPara validateParameters(encryptorId, encryptorParameters); final ServerEncryptor encryptor; switch (encryptorParameters.getProtocolVersion()) { - case "3.2", "3.1", "3.0" -> { + case "3.3", "3.2", "3.1", "3.0" -> { encryptor = new ServerEciesEncryptor(encryptorId, encryptorParameters); } default -> { @@ -154,7 +154,7 @@ public RequestResponseValidator getRequestResponseValidator(String protocolVersi throw new EncryptorException("Missing protocolVersion parameter"); } switch (protocolVersion) { - case "3.2", "3.1", "3.0" -> { + case "3.3", "3.2", "3.1", "3.0" -> { return new EciesRequestResponseValidator(protocolVersion); } default -> { diff --git a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/ecies/ClientEciesEncryptor.java b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/ecies/ClientEciesEncryptor.java index 86cd1792e..461eaadfd 100644 --- a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/ecies/ClientEciesEncryptor.java +++ b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/ecies/ClientEciesEncryptor.java @@ -79,7 +79,8 @@ public ClientEciesEncryptor(EncryptorId encryptorId, EncryptorParameters paramet encryptorId.scope(), parameters.getProtocolVersion(), parameters.getApplicationKey(), - parameters.getActivationIdentifier() + parameters.getActivationIdentifier(), + parameters.getTemporaryKeyId() ); } @@ -156,6 +157,7 @@ public EncryptedRequest encryptRequest(byte[] data) throws EncryptorException { } return new EncryptedRequest( + encryptorParameters.getTemporaryKeyId(), base64Encoder.encodeToString(eciesCryptogram.getEphemeralPublicKey()), base64Encoder.encodeToString(eciesCryptogram.getEncryptedData()), base64Encoder.encodeToString(eciesCryptogram.getMac()), diff --git a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/ecies/EciesRequestResponseValidator.java b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/ecies/EciesRequestResponseValidator.java index e6b14e341..444942f9e 100644 --- a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/ecies/EciesRequestResponseValidator.java +++ b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/ecies/EciesRequestResponseValidator.java @@ -33,7 +33,7 @@ public class EciesRequestResponseValidator implements RequestResponseValidator { /** * Protocol versions supported in this validator. */ - private final static Set supportedVersions = Set.of("3.2", "3.1", "3.0"); + private final static Set supportedVersions = Set.of("3.3", "3.2", "3.1", "3.0"); /** * Indicate that request and response must contain timestamp and nonce. This is valid for protocol V3.2+. @@ -53,8 +53,8 @@ public EciesRequestResponseValidator(String protocolVersion) throws EncryptorExc if (!supportedVersions.contains(protocolVersion)) { throw new EncryptorException("Unsupported protocol version " + protocolVersion); } - this.useTimestamp = "3.2".equals(protocolVersion); - this.useNonceForRequest = "3.2".equals(protocolVersion) || "3.1".equals(protocolVersion); + this.useTimestamp = "3.3".equals(protocolVersion) || "3.2".equals(protocolVersion); + this.useNonceForRequest = "3.3".equals(protocolVersion) || "3.2".equals(protocolVersion) || "3.1".equals(protocolVersion); } @Override diff --git a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/ecies/ServerEciesEncryptor.java b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/ecies/ServerEciesEncryptor.java index c62e2e75b..d53a7c838 100644 --- a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/ecies/ServerEciesEncryptor.java +++ b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/ecies/ServerEciesEncryptor.java @@ -81,7 +81,8 @@ public ServerEciesEncryptor(EncryptorId encryptorId, EncryptorParameters paramet encryptorId.scope(), parameters.getProtocolVersion(), parameters.getApplicationKey(), - parameters.getActivationIdentifier() + parameters.getActivationIdentifier(), + parameters.getTemporaryKeyId() ); } diff --git a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/model/EncryptedRequest.java b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/model/EncryptedRequest.java index 7b5a5e8c7..567d7eade 100644 --- a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/model/EncryptedRequest.java +++ b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/model/EncryptedRequest.java @@ -26,6 +26,7 @@ @Data @AllArgsConstructor public class EncryptedRequest { + private String temporaryKeyId; private String ephemeralPublicKey; private String encryptedData; private String mac; diff --git a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/model/EncryptorParameters.java b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/model/EncryptorParameters.java index 4ffe51f10..a542aec8e 100644 --- a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/model/EncryptorParameters.java +++ b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/encryptor/model/EncryptorParameters.java @@ -33,4 +33,5 @@ public class EncryptorParameters { private String protocolVersion; private String applicationKey; private String activationIdentifier; + private String temporaryKeyId; } diff --git a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/util/EciesUtils.java b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/util/EciesUtils.java index b9c15dd1f..76c6039fa 100644 --- a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/util/EciesUtils.java +++ b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/util/EciesUtils.java @@ -62,27 +62,47 @@ public static long generateTimestamp() { * @param protocolVersion Protocol version. * @param applicationKey Application key. * @param activationId Activation ID. + * @param temporaryKeyId Temporary key ID. * @return Derived associated data. * @throws EciesException In case that activation ID is required but is missing. */ - public static byte[] deriveAssociatedData(EncryptorScope scope, String protocolVersion, String applicationKey, String activationId) throws EciesException { + public static byte[] deriveAssociatedData(EncryptorScope scope, String protocolVersion, String applicationKey, String activationId, String temporaryKeyId) throws EciesException { if (protocolVersion == null) { throw new EciesException("Protocol version is missing"); } - if ("3.2".equals(protocolVersion)) { - if (applicationKey == null) { - throw new EciesException("Application key is missing"); + switch (protocolVersion) { + case "3.2": { + if (applicationKey == null) { + throw new EciesException("Application key is missing"); + } + if (scope == EncryptorScope.ACTIVATION_SCOPE) { + if (activationId == null) { + throw new EciesException("Activation ID is missing in ACTIVATION_SCOPE"); + } + return ByteUtils.concatStrings(protocolVersion, applicationKey, activationId); + } else { + return ByteUtils.concatStrings(protocolVersion, applicationKey); + } } - if (scope == EncryptorScope.ACTIVATION_SCOPE) { - if (activationId == null) { - throw new EciesException("Activation ID is missing in ACTIVATION_SCOPE"); + case "3.3": { + if (applicationKey == null) { + throw new EciesException("Application key is missing"); + } + if (temporaryKeyId == null) { + throw new EciesException("Missing temporary key identifier"); + } + if (scope == EncryptorScope.ACTIVATION_SCOPE) { + if (activationId == null) { + throw new EciesException("Activation ID is missing in ACTIVATION_SCOPE"); + } + return ByteUtils.concatStrings(protocolVersion, applicationKey, activationId, temporaryKeyId); + } else { + return ByteUtils.concatStrings(protocolVersion, applicationKey, temporaryKeyId); } - return ByteUtils.concatStrings(protocolVersion, applicationKey, activationId); - } else { - return ByteUtils.concatStrings(protocolVersion, applicationKey); } - } else { - return null; + default: { + return null; + } } } @@ -130,24 +150,28 @@ public static byte[] deriveSharedInfo2(String protocolVersion, byte[] sharedInfo if (sharedInfo2Base == null) { throw new EciesException("Missing sharedInfo2Base parameter"); } - if ("3.2".equals(protocolVersion)) { - if (nonce == null) { - throw new EciesException("Missing nonce parameter"); - } - if (timestamp == null) { - throw new EciesException("Missing timestamp parameter"); + switch (protocolVersion) { + case "3.3", "3.2": { + if (nonce == null) { + throw new EciesException("Missing nonce parameter"); + } + if (timestamp == null) { + throw new EciesException("Missing timestamp parameter"); + } + if (associatedData == null) { + throw new EciesException("Missing associatedData parameter"); + } + return ByteUtils.concatWithSizes( + sharedInfo2Base, + nonce, + ByteBuffer.allocate(Long.BYTES).putLong(timestamp).array(), + ephemeralPublicKey, + associatedData); } - if (associatedData == null) { - throw new EciesException("Missing associatedData parameter"); + default: { + return sharedInfo2Base; } - return ByteUtils.concatWithSizes( - sharedInfo2Base, - nonce, - ByteBuffer.allocate(Long.BYTES).putLong(timestamp).array(), - ephemeralPublicKey, - associatedData); } - return sharedInfo2Base; } } 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 897f921fc..8382d09d2 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 @@ -102,7 +102,7 @@ public byte[] computeTokenDigest(byte[] nonce, byte[] timestamp, String version, 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.3", "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); } diff --git a/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/encryption/GeneralEncryptorTest.java b/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/encryption/GeneralEncryptorTest.java index 637d95094..59e6a1227 100644 --- a/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/encryption/GeneralEncryptorTest.java +++ b/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/encryption/GeneralEncryptorTest.java @@ -75,6 +75,8 @@ private static class TestConfiguration { final String activationId; final KeyPair keyMasterServer; final KeyPair keyServer; + final String tempKeyApplication; + final String tempKeyActivation; } private TestConfiguration configuration; @@ -99,7 +101,9 @@ public void configureKeys() throws Exception { keyGenerator.generateRandomBytes(16), UUID.randomUUID().toString(), keyGenerator.generateKeyPair(), - keyGenerator.generateKeyPair() + keyGenerator.generateKeyPair(), + UUID.randomUUID().toString(), + UUID.randomUUID().toString() ); } @@ -385,12 +389,12 @@ void testRequestResponseObjectValidation(String version, EncryptorId encryptorId request.setEphemeralPublicKey(null); assertFalse(validator.validateEncryptedRequest(request)); - if ("3.1".equals(version) || "3.2".equals(version)) { + if ("3.1".equals(version) || "3.2".equals(version) || "3.3".equals(version)) { request = copyRequest(validRequest); request.setNonce(null); assertFalse(validator.validateEncryptedRequest(request)); } - if ("3.2".equals(version)) { + if ("3.2".equals(version) || "3.3".equals(version)) { request = copyRequest(validRequest); request.setTimestamp(null); assertFalse(validator.validateEncryptedRequest(request)); @@ -420,7 +424,7 @@ void testRequestResponseObjectValidation(String version, EncryptorId encryptorId response = copyResponse(validResponse); response.setEncryptedData(null); assertFalse(validator.validateEncryptedResponse(response)); - if ("3.2".equals(version)) { + if ("3.2".equals(version) || "3.3".equals(version)) { response = copyResponse(validResponse); response.setTimestamp(null); assertFalse(validator.validateEncryptedResponse(response)); @@ -452,8 +456,9 @@ private EncryptedResponse copyResponse(EncryptedResponse response) { * Make new instance of encrypted request object with identical values copied from the provided object. * @param request Request object to copy. * @return Copy of provided request object. - */ private EncryptedRequest copyRequest(EncryptedRequest request) { - return new EncryptedRequest(request.getEphemeralPublicKey(), request.getEncryptedData(), request.getMac(), request.getNonce(), request.getTimestamp()); + */ + private EncryptedRequest copyRequest(EncryptedRequest request) { + return new EncryptedRequest(request.getTemporaryKeyId(), request.getEphemeralPublicKey(), request.getEncryptedData(), request.getMac(), request.getNonce(), request.getTimestamp()); } /** @@ -466,6 +471,7 @@ public void testEncryptDecryptV30() throws Exception { @Override public void validateRequest(EncryptedRequest request) throws Exception { assertNotNull(request); + assertNull(request.getTemporaryKeyId()); assertNotNull(request.getEphemeralPublicKey()); assertNotNull(request.getEncryptedData()); assertNotNull(request.getMac()); @@ -494,6 +500,7 @@ public void testEncryptDecryptV31() throws Exception { @Override public void validateRequest(EncryptedRequest request) throws Exception { assertNotNull(request); + assertNull(request.getTemporaryKeyId()); assertNotNull(request.getEphemeralPublicKey()); assertNotNull(request.getEncryptedData()); assertNotNull(request.getMac()); @@ -522,6 +529,36 @@ public void testEncryptDecryptV32() throws Exception { @Override public void validateRequest(EncryptedRequest request) throws Exception { assertNotNull(request); + assertNull(request.getTemporaryKeyId()); + assertNotNull(request.getEphemeralPublicKey()); + assertNotNull(request.getEncryptedData()); + assertNotNull(request.getMac()); + assertNotNull(request.getNonce()); + assertNotNull(request.getTimestamp()); + } + + @Override + public void validateResponse(EncryptedResponse response) throws Exception { + assertNotNull(response); + assertNotNull(response.getEncryptedData()); + assertNotNull(response.getMac()); + assertNotNull(response.getNonce()); + assertNotNull(response.getTimestamp()); + } + }); + } + + /** + * Test general encrypt-decrypt routines with using protocol 3.3. + * @throws Exception In case of failure. + */ + @Test + public void testEncryptDecryptV33() throws Exception { + testGenericEncryptor("3.3", new DataValidator() { + @Override + public void validateRequest(EncryptedRequest request) throws Exception { + assertNotNull(request); + assertNotNull(request.getTemporaryKeyId()); assertNotNull(request.getEphemeralPublicKey()); assertNotNull(request.getEncryptedData()); assertNotNull(request.getMac()); @@ -658,6 +695,7 @@ public void testVectors_3_2() throws Exception { // Requests final EncryptedRequest[] encryptedRequest = { new EncryptedRequest( + null, "Avlav7hfDwCA1zJq6gyczWtUn+MhNCebikIH7rkUkoHB", "jZ1y4ZkJpvRTDHFXQ+J9jsWaFuV0AvqpUXFDCi3bH90YCutTufSamKXpEIhFfqBmhzYak2g6LBUfgmTJ7c74D+eOqGRn1EwZOcgVHKbaFjgthwSUnD8E7maEK9u5qmVdi52drt9vQ1Cye5jWn0vSTKmvSkfcQcmK42o/0r/8LXs=", "ovJWPbaRr/+9nDLwHhej1u9iNVg0OVVNNO2zI88AM9g=", @@ -665,6 +703,7 @@ public void testVectors_3_2() throws Exception { 1691762307382L ), new EncryptedRequest( + null, "A97NlW0JPLJfpG0AUvaRHRGSHh+quZu+u0c+yxsK7Xji", "qYLONkDWFpXefTKPbaKTA/PWdRYH5pk9uvGjUqSYbeK7Q0aOohK2MknTyviyNuSp", "DNlZdsM1wgH8v2mAROjj3vmQu4DI4ZJnuTBzQMrHsew=", @@ -672,6 +711,7 @@ public void testVectors_3_2() throws Exception { 1691762307384L ), new EncryptedRequest( + null, "AtSsPjiwbh3GnWYjCOejGIGg0LEbl1X6SY4f1F77PG2I", "px6h9Hu+wyH38YySO6istbinaF3ALyrBraad0qhTCJZrYrVlTv1bEnfvElBupQzGUx3SikSqaOjR+UKzj9TVfa2rw36LkSIVFZYk1gG6xW3U852ZvJpuTtw6h7WhFYks", "bySXBDU/9mDx9T8i9DFWX7Xn4O6HZK2EMLpA+ogv3eM=", @@ -679,6 +719,7 @@ public void testVectors_3_2() throws Exception { 1691762307384L ), new EncryptedRequest( + null, "AnjhcBNyzpyUs8TnvW164zfwVk6UQjof8zueumjUADlB", "rQDj9EseF9GvJY6a0YCExA==", "Mpu0lek/SXf7JvxnlEngv/Bx8nFhxi54vHVrBr0f7H8=", @@ -686,6 +727,7 @@ public void testVectors_3_2() throws Exception { 1691762307385L ), new EncryptedRequest( + null, "Aqa/2aW4VuZTXaFoc0rcc67RotG0rbiqpvontLsdoLIe", "ic3LxIfwgK9XbckAxivYvMdwuAL9nOC/Kdry4w/1xRw=", "OyQcPCU8opsBN88vCE/9Km53a8sNqamIMIwxNfOOyto=", @@ -693,6 +735,7 @@ public void testVectors_3_2() throws Exception { 1691762307385L ), new EncryptedRequest( + null, "Aomhgt+8zAMsuRYgsVJMioFFPLP6eK+4omcLfftS/PHK", "xNdtHsq28x+cFGxLGJbW6l7SscETdLRHejmXYETzU8670YyaqpiGOO5276vb3XDnxM6GjKHEztXruz8YBQzWKYqc6YVU4WqKMNHBu1A/9yKY8KGE+XsSxyrkZxoIM4oZuUp7p1ui+H87PPY8Vs/c9dMM5YUMYVUFZA1kBnzskKs=", "z05w9DN9CKWtURAr0g7D5Kya8Jvp+CQFLNz2Fy1inaI=", @@ -700,6 +743,7 @@ public void testVectors_3_2() throws Exception { 1691762307385L ), new EncryptedRequest( + null, "AoCXG9cbmKBSPP2zi3pOuJQV6dENZ751dUhEGoDqLWVB", "fqsJXWuIt2rwwsWLu8TbPnCxwha6PTGTpzmsLq/Tdynt5YcrEBk9wlRaQIXzWi0KbES20BjJbgL7JIaY2qj/XlFU+vxB+vybUnHrtpe2NaDthaYgdEecX3W1uzpyd745ogDSGe19gOqwXCFCRFLF+w==", "T/tx0z+61zPosCa2Y0oJBepFOOfn0O1lrMKkr9RSVNY=", @@ -707,6 +751,7 @@ public void testVectors_3_2() throws Exception { 1691762307386L ), new EncryptedRequest( + null, "A/5KJP3Cb8DhNjo8Cs2juYLwpswsUBJe6XXdwowIelP7", "wUXXg0vgkZjqvqIfJm7YPgk+7bwgWSttizi+uSKAE4z8dOY8zUp0uvsvsUqDIvnhisnc82IyS/kGhSg1QWyzjAdfr5rWehl+aS+e8GPIu3Ok8n0qNG9TJ1n/UxuD6Ok/WTCHsRW2QoU2I8vB6BAMUw==", "J88D9JrcVVmVlUNe5g6IzEHd3m+PqfSzBNyCfEb+UXg=", @@ -714,6 +759,7 @@ public void testVectors_3_2() throws Exception { 1691762307386L ), new EncryptedRequest( + null, "A3TP+jPFrRgQd563V8goh2wJgvRS9eMpwjo9tOivLboN", "8MjZ4+3cUC7IkwyNK09WSDMOrMpNwfHrXUM3A/19sjyOVZJIAl9HYJySlN8h9A2qrG7l0Eu6nFUwjDH8+NHfqBHCdOAnpncwgANE5GetzgA=", "pmWeeMSroONdztB05rb6932llfAJJo6+uqLvwYq01dw=", @@ -721,6 +767,7 @@ public void testVectors_3_2() throws Exception { 1691762307386L ), new EncryptedRequest( + null, "A0w7WTl0Q3vhxlyKJWV1hM1YC484mysCqhjay9uFSmvG", "K0Ep8dWNhD99yZm/mShFy53DYbTCntm582rlWwskPfcKTE7b/7gBFbXaGly1o9cmQ9Wv9RjBx8Ai4rda/KKbyMq3ZaX6ljAWFpOmqUIgMUQ=", "Zr7vEn6WBYkFFZRAvq3UdRR/OWF2uOK0ABik9fytOUo=", @@ -728,6 +775,7 @@ public void testVectors_3_2() throws Exception { 1691762307387L ), new EncryptedRequest( + null, "A4o3ZVufjyXvJnc98rvHxTbQgCpY1dwMkJs4mKkT78up", "8hYJGXgHLD8tH9sFrRlU6fxGWU/JdlSBpPkL178OFRdORMXTY/ReMRbajQD3bXKzXjmhdYR5X13fHsmiuvHIQVPRFB0ZyS43HT/uEDpWh8SWByKjNB5je6ftEySsmpKGp0KvmjXgiIRX7TiRzwJ03g==", "VX9TB4hPM7/6U/NQvBNR6VaP1loyq2ZhcmEu4NWCU7g=", @@ -735,6 +783,7 @@ public void testVectors_3_2() throws Exception { 1691762307387L ), new EncryptedRequest( + null, "AhVR4QxfHA5resv8ppMANxzZwkaWphsmtA/EENi8Swjp", "ASC8xiBSyjx8wGwf71U9Zk4nZT9w//8AafiZaT+9RtObUmb1HjguWv3Xpqejnf5kml3Z7sXDYgFemFYLklhL5A==", "8wlb+Pz3UulREpbcBV4GfiY4bePugBPV6ywgaycvrpU=", @@ -742,6 +791,7 @@ public void testVectors_3_2() throws Exception { 1691762307387L ), new EncryptedRequest( + null, "A9ok7XXLWWWtQAxERdvFv3I31D+pgZuY3cVSbjpJHLda", "+b0Ki6WcoaoGJhBrGR28zeMqS91XMmCCtO/HU3xaKNg=", "jmkaGcZ+qnrMXtD1R7YhRmJJU+d3y6/nATjNno7DA0A=", @@ -749,6 +799,7 @@ public void testVectors_3_2() throws Exception { 1691762307388L ), new EncryptedRequest( + null, "A24fQipKuaW7sOmXbpZDW+QetW/aBmS+2fkrkSdNDlQe", "GaXg6TBM+H4ru/E25gvV0g==", "xV19DEuOG+SGpT22GU55mVQqU4I7/+vgWNFKDq6tK5k=", @@ -756,6 +807,7 @@ public void testVectors_3_2() throws Exception { 1691762307388L ), new EncryptedRequest( + null, "ArzfJWjDZrjndvQg3aFxZme6w/Z5P4uV4mBClCbURJuv", "cbG2zh4dp5Ig65/Gdz97ZLm1vWeLfSUbIIoLWQXQm5pUVLkHJ55Mrl4TwdK6kTG0", "lawZCFwh0NTpNafMwC92/ndMnkryG4yxfAvp/4q1F3Y=", @@ -763,6 +815,7 @@ public void testVectors_3_2() throws Exception { 1691762307388L ), new EncryptedRequest( + null, "At3TEHVJmtO+VPUtJ/ijXYhx1BAnjcDnQRk9AbhukeWa", "4RPt1tswWfapZNWU7gFkuMyUADjsykdAQHQsMXHmghDE3l7dVYiMctKuj8RHFLAIsgI09toZelMAPRE1PLJz6g==", "JgkwHwwwoDb14zokbecDQeqmOrJxRO0Lddv1sQp0bnQ=", @@ -886,12 +939,12 @@ public void testVectors_3_2() throws Exception { final ServerEncryptor serverEncryptor; if (scope == EncryptorScope.APPLICATION_SCOPE) { serverEncryptor = encryptorFactory.getServerEncryptor(eid, - new EncryptorParameters("3.2", applicationKey, null), + new EncryptorParameters("3.2", applicationKey, null, null), new ServerEncryptorSecrets(masterServerPrivateKey, applicationSecret) ); } else { serverEncryptor = encryptorFactory.getServerEncryptor(eid, - new EncryptorParameters("3.2", applicationKey, activationId), + new EncryptorParameters("3.2", applicationKey, activationId, null), new ServerEncryptorSecrets(serverPrivateKey, applicationSecret, transportKey) ); } @@ -901,6 +954,382 @@ public void testVectors_3_2() throws Exception { } } + /** + * Test encryptor with using test vectors generated by PowerAuth Mobile SDK (iOS). The protocol version is fixed to 3.3. + * @throws Exception In case of failure. + */ + @Test + public void testVectors_3_3() throws Exception { + // Paste vectors here (generated by iOS unit tests) + // ---------------------------- + + // Shared constants + final PrivateKey masterServerPrivateKey = keyConvertor.convertBytesToPrivateKey(ByteUtils.concat(new byte[1], Base64.getDecoder().decode("oG1PJWwflQ8XRt4Nf4uzyBf0w0D4jNW22JxfImj4i5w="))); + final PublicKey masterServerPublicKey = keyConvertor.convertBytesToPublicKey(Base64.getDecoder().decode("Au12Pbz70flr9eizmYC72P3vPp/h2KWlmvcvfssF6xBt")); + final PrivateKey serverPrivateKey = keyConvertor.convertBytesToPrivateKey(ByteUtils.concat(new byte[1], Base64.getDecoder().decode("98pEwpFj60r8REpXzrflb5kzgj1aoxg1YEuKb0Kuwyk="))); + final PublicKey serverPublicKey = keyConvertor.convertBytesToPublicKey(Base64.getDecoder().decode("AjG7M9W9qNUOu51dJROO4NE+xOnqppxxyFU1Tn3FhXui")); + final String tempKeyIdApplication = "D3D82A6B-47CF-4225-BBE5-BAD96FB84CA4"; + final String tempKeyIdActivation = "1221CD15-9092-4779-A157-04DC229A63F7"; + final String activationId = "CF2E9A48-9085-4AA3-8F85-FFAFD2380609"; + final String applicationKey = "WQBeNgCHGlW58rzUlP7Ehg=="; + final String applicationSecret = "Epbv1D+tibvvkqGIyDOT5g=="; + final byte[] transportKey = Base64.getDecoder().decode("EsOk4R701klML5Ljd07Y5Q=="); + // Original request data + final byte[][] plainRequestData = { + Base64.getDecoder().decode("f+jScpA8qs2OAR2TWqnDD6W00yUYsdIGuE1nCsqKvVBDfedwA6XBHy4z/ey3"), + Base64.getDecoder().decode("5jM1pRKPJpkv16zg9A5ZcEY3KXGr3p2de1hWZVsVKXL7PIzljrl2Lxg3RfWuf9myS17OBu7d2nO7SD1Sl3U2KtJA3+B1c202TqdQEXRT"), + Base64.getDecoder().decode("K6cp8f5FyfsE3kv2HJubaJ9b5ILXAMc="), + Base64.getDecoder().decode("5p4zk5/DaPiw2oFP0LSygOJD/VDGEfPQMcI1JO1iSqO4XYUr0yeKciDFxQ5r9Ji8C8ETJKD1/5hlJGURXw=="), + Base64.getDecoder().decode("jC7527ZbuLU3ddoeSHOaE2f93sqL9IKyf9pjoIpU/6h0DowFlVmMibIyKWnL2dkDmKeIGFhh4EzvEcAnk7b5bU9Jv7ItenE3bxDu55NQXQs2XjZLqwb+gdjt6f2dZx6s3K/1+hG8zv2QYc1y5Ielnus="), + Base64.getDecoder().decode("17e8s/ckRIR52A964Vb/AXZ/Gcv4yT1RCS42ZUiwegzk"), + Base64.getDecoder().decode("6KNE7ibjx5Hx6OOeVl6FcvHBueCvds5nzUE2CBgJ/15chbQQM+Qghg02so06AgaDHEIdyuiA8wREEwHSDDwUsDbYbSZGsJcXFWZmtIutzbTsL08zg9HsjgtWc+I7IX3n6T286Q=="), + Base64.getDecoder().decode("OhwnzC44O5E8bplAyUT+HjAoJ5nuaXxpZryl17DHSmHFBRjejBznYYHCl2UUDYTpgT00j8Fvu+GtS3i9jr704r/z5XENGsb5aqitVERSiPQDWXHSeF5w/L45U535NzjJCv9gudDSXrPaP2mB"), + Base64.getDecoder().decode("EsSeJzVFi30Ph7KGBamnpavP2IVJQyXSyh3AR/YX5w9hRVsT7dEqVrCvP7WSRX5X9HCvQU3aqqB/OLVGMF8B81o08p/7WExeaf1PylcbRqomHwqBgO64LdAXa80="), + Base64.getDecoder().decode("PNhn+JpA6ivlcZXpYBM9SJgAqrGUJ1Fs422sJDJyHqPFmBaZOlyYQGM3hSexgNtU47iQyiz+qfdslFNszKiCohV1fx0C6nmH4xn96333ISVx7i8YmM+SI06LWfdb"), + Base64.getDecoder().decode("w/kWbwDE27WzyTzi/SNm7a4V7MGZaShVR9LaSaj+y0nT/6CBfdk/4POlqyXpJD31D+mL7c8z2dOFyktHNJccliODZI0="), + Base64.getDecoder().decode("QHMC/ZEQ0A1uEQtslxYtaeBCI4R8cklIjOThRuCykszKHq5cnYjARUIFLiHzDfClIwZIxaRY7qm4etYWiwzxv9pEI2y08dtWfeywaroWFUPJI+Zr5/1S79fDleYx2QYqxZnBFVogSNgg7A9eOxRtv99/u96atw=="), + Base64.getDecoder().decode("oHXR8sAoeoo+o9RzysQqiZeYkQffKDf5ab+RZNyrF9jax+eVEIhA6uOrZ784aw8CnzKqqJNRW352T1l7JbliEhhtTllzqjY3g3KMGI+vEg=="), + Base64.getDecoder().decode("rpPcobnE/XGR56rklurFfgyiGO2EMwhlM3a6rNo1DjTZcsCFGXW2e01c7T03RlkdJhihJwCwRFIA1shW6RdCi/mE1KF9X0g8Z3i5e9acegsjeL1i3xcgXUzh8j3dntsrh1N6SsY="), + Base64.getDecoder().decode("tW44GiuzI4cYlPRuRk9xSzQBkISv1BS+vIvZMGufm3acrE9w0QoUgzt1YZV0kHRVJy1+smchfK42"), + Base64.getDecoder().decode("GxTDg2vEtfGvOdhRbZI5b08gE/YL1uEk0dAYBgbmf4cywD6t0ItWtaJgTTK1OC4YAztf1WxCyG8="), + }; + // Original response data + final byte[][] plainResponseData = { + Base64.getDecoder().decode("Q0o+ObtisXK/MO/0W+DggFD6cnlhUrSCHocN3Mu1IYrFgxswSk2VELlCF3U7OzPwFS1g3vcwxTYdjCGyyAcVECODy68Dd2Tv0vLlDfYjB5D8+E75BCrYhwRbh3W3OaC0VxI8V3xh125mFx0PWRXJuxf1yKB3rtY="), + Base64.getDecoder().decode("6UfrYjWYCkBIK9Ori7qB1KEfWwz5DYGVaKYxcz8OLWpfO8xtON8xa4a9ORaTRCKbKYMHh6zloo5/Zn7bZ8YmguicAmWB1gqqwtUDyYtTMwAjyXLmKs2shftLQYtauUSkWNc="), + Base64.getDecoder().decode("GMHLlB1cZzelL0+5/JUOVnUzI44eN54zxA=="), + Base64.getDecoder().decode("qYTFk6IaB2B3roQRjIyzAzegiRSgVpPmjifyQQ7e+fWKwm8="), + Base64.getDecoder().decode("Cl0eRW9Aq7auie9qaXpYsWbES2fNmbqRM6U2sxU="), + Base64.getDecoder().decode("vhdJ0uPZVyeVEdxSo3ErO2Dogay5oL7b/cL/BRhellDBq8X67puO+50fgOAgfL0bpQMZBZh/uLgxBrGf2bVOzTpO8R6WOYxjg0FnOdb91/VbGSvTncwbX71U"), + Base64.getDecoder().decode("/QKbpOxjKicszPmiM6HjPejXRYwfVJowveYeCwYMSFb4vDP4P0jJCLqsCIAVQwzqMs0DcVjBMQgaaE9an7z+sVQ0M15xYgRqdg=="), + Base64.getDecoder().decode("x/WlUGQzvMB1zu64EYtpzq8="), + Base64.getDecoder().decode("k0+sImOGUwOb/1s8U1uI5uZ8gZaszNuU4pKWq2d775m/iAUB7f0o6kVnfDzZZvEXfEzXlKZsdzf2bE/5KJ1q2WsMhxwlbPCZ+zWzhD3lPMueXK7Sas8EOQ=="), + Base64.getDecoder().decode("qxljpcx47/22kqbxnjZhbDq6tL8nWJp9fcR/bN7/dh64rsLxeT2mQdQAdhUw8bMbUlv113sco8bI+Y0z/R4ZWlDThcLus6WZOyizKEVipIZzAteUmWww"), + Base64.getDecoder().decode("AMC6x6qz309wM6mbk85poct0k18dW4Xg0TyzqNRMOrNxdESxgdt+X7uqINrGGT80uaDuk8K5BXgd6vIGn0cnPkiW"), + Base64.getDecoder().decode("zZZA"), + Base64.getDecoder().decode("F6aVUJhxIkRBjsyPk1yH"), + Base64.getDecoder().decode("Pkl94I9MOlQmYJEXBhu0EtRPygUtB7a3GP6+uaXCu6wAF8Ky9pjUKPNvtmLtR1v1Svspml7W3EjeEWXc2Zk6bEjN6x4+Jh7ilR2c5QZOySRv72c="), + Base64.getDecoder().decode("Ggd98d/1vIPsmJqV2yry1je2eXYrHUQNiGFATp6JoKJX2w=="), + Base64.getDecoder().decode("EKHnpKeG7l8q+Q9go+QZzJVV3+mcYNWmjC9wqzoipDje6tz3yarhobMvuZhXHN3Kx9keC0V30QE="), + }; + // EncryptorIds + final EncryptorId[] encryptorIds = { + EncryptorId.APPLICATION_SCOPE_GENERIC, + EncryptorId.ACTIVATION_SCOPE_GENERIC, + EncryptorId.ACTIVATION_LAYER_2, + EncryptorId.UPGRADE, + EncryptorId.VAULT_UNLOCK, + EncryptorId.CREATE_TOKEN, + EncryptorId.CONFIRM_RECOVERY_CODE, + EncryptorId.APPLICATION_SCOPE_GENERIC, + EncryptorId.ACTIVATION_SCOPE_GENERIC, + EncryptorId.ACTIVATION_LAYER_2, + EncryptorId.UPGRADE, + EncryptorId.VAULT_UNLOCK, + EncryptorId.CREATE_TOKEN, + EncryptorId.CONFIRM_RECOVERY_CODE, + EncryptorId.APPLICATION_SCOPE_GENERIC, + EncryptorId.ACTIVATION_SCOPE_GENERIC, + }; + // Associated data + final byte[][] associatedData = { + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkRDNEODJBNkItNDdDRi00MjI1LUJCRTUtQkFEOTZGQjg0Q0E0"), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkQ0YyRTlBNDgtOTA4NS00QUEzLThGODUtRkZBRkQyMzgwNjA5AAAAJDEyMjFDRDE1LTkwOTItNDc3OS1BMTU3LTA0REMyMjlBNjNGNw=="), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkRDNEODJBNkItNDdDRi00MjI1LUJCRTUtQkFEOTZGQjg0Q0E0"), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkQ0YyRTlBNDgtOTA4NS00QUEzLThGODUtRkZBRkQyMzgwNjA5AAAAJDEyMjFDRDE1LTkwOTItNDc3OS1BMTU3LTA0REMyMjlBNjNGNw=="), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkQ0YyRTlBNDgtOTA4NS00QUEzLThGODUtRkZBRkQyMzgwNjA5AAAAJDEyMjFDRDE1LTkwOTItNDc3OS1BMTU3LTA0REMyMjlBNjNGNw=="), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkQ0YyRTlBNDgtOTA4NS00QUEzLThGODUtRkZBRkQyMzgwNjA5AAAAJDEyMjFDRDE1LTkwOTItNDc3OS1BMTU3LTA0REMyMjlBNjNGNw=="), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkQ0YyRTlBNDgtOTA4NS00QUEzLThGODUtRkZBRkQyMzgwNjA5AAAAJDEyMjFDRDE1LTkwOTItNDc3OS1BMTU3LTA0REMyMjlBNjNGNw=="), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkRDNEODJBNkItNDdDRi00MjI1LUJCRTUtQkFEOTZGQjg0Q0E0"), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkQ0YyRTlBNDgtOTA4NS00QUEzLThGODUtRkZBRkQyMzgwNjA5AAAAJDEyMjFDRDE1LTkwOTItNDc3OS1BMTU3LTA0REMyMjlBNjNGNw=="), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkRDNEODJBNkItNDdDRi00MjI1LUJCRTUtQkFEOTZGQjg0Q0E0"), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkQ0YyRTlBNDgtOTA4NS00QUEzLThGODUtRkZBRkQyMzgwNjA5AAAAJDEyMjFDRDE1LTkwOTItNDc3OS1BMTU3LTA0REMyMjlBNjNGNw=="), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkQ0YyRTlBNDgtOTA4NS00QUEzLThGODUtRkZBRkQyMzgwNjA5AAAAJDEyMjFDRDE1LTkwOTItNDc3OS1BMTU3LTA0REMyMjlBNjNGNw=="), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkQ0YyRTlBNDgtOTA4NS00QUEzLThGODUtRkZBRkQyMzgwNjA5AAAAJDEyMjFDRDE1LTkwOTItNDc3OS1BMTU3LTA0REMyMjlBNjNGNw=="), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkQ0YyRTlBNDgtOTA4NS00QUEzLThGODUtRkZBRkQyMzgwNjA5AAAAJDEyMjFDRDE1LTkwOTItNDc3OS1BMTU3LTA0REMyMjlBNjNGNw=="), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkRDNEODJBNkItNDdDRi00MjI1LUJCRTUtQkFEOTZGQjg0Q0E0"), + Base64.getDecoder().decode("AAAAAzMuMwAAABhXUUJlTmdDSEdsVzU4cnpVbFA3RWhnPT0AAAAkQ0YyRTlBNDgtOTA4NS00QUEzLThGODUtRkZBRkQyMzgwNjA5AAAAJDEyMjFDRDE1LTkwOTItNDc3OS1BMTU3LTA0REMyMjlBNjNGNw=="), + }; + // Envelope keys + final byte[][] envelopeKeys = { + Base64.getDecoder().decode("k074hGF+oBZMhhh6BS6CY+4/aaN5TrIwDsVEwn/WjyXWgNSqshjiANmOR36L/Shc"), + Base64.getDecoder().decode("ocMfq8QlGi+/5e/xilUCZUxqh1Z4PqZmmNgmDnm1BLZbFZuh8pFvx28zAo8moHkz"), + Base64.getDecoder().decode("XSS+JT0S8o2fXPArZZ/MY+9MqExJV5pG1lCrSJwzlY/i5irGdshKl5PN2h8mChNm"), + Base64.getDecoder().decode("8FIKg1R4BQFtlANmy0f27fWQaINgL9vlr3hLym/xt1MQ3bofjwVIYqu7wGiJD43n"), + Base64.getDecoder().decode("OaRGAw2XdkzsHzcUXj8l/uglAVVFtuzMjvR9+5+kTFIz+9SP4KDXJwugYEZ3sL6u"), + Base64.getDecoder().decode("JBm52ZtwKYBBxV7Ar5Wtf4Y9OTDv9OU2pFEv7WJYA74yMJRQcALWugqV79CG5Aqf"), + Base64.getDecoder().decode("2YtkBfXRrhUffeu98I38CCfdkR33/8c+C82j52YSIlwJ5KcauOk47WXjOczOkFsg"), + Base64.getDecoder().decode("LpfRIkzTWQYF4458Wxx3qEUvwBpRKugRHQdaC9bBp0jtkdPpRXCQKSXO8xCjZUIx"), + Base64.getDecoder().decode("eP8jZvzxPBOv7E+w39z2JsGJEXNskfxQgPV8R0X4aY9nlgyESMa8A5fbrAgh70QY"), + Base64.getDecoder().decode("kScXW3XPZF8vQzwAPs1H1kH8V7nT1TRXHpYRKI8LrnZ37VEtToEKizwxAW8YV67A"), + Base64.getDecoder().decode("1jpx3WEzDxbt2hjfTY/3rEbVTuhZagFLxhZne9l3N17jJov2hrOd2Vc8tJfKDGXC"), + Base64.getDecoder().decode("A0sds7ZIaPKsR10Q7ai/E/Y8grHSbS4WYKck4zLVEdkejcDwXpAvRfUcxg7bw+fm"), + Base64.getDecoder().decode("u1wtm4Ll21Y5FkSF9lbURDcuz425PK6HOSKWoMgUZMeMjwvBtJIdkXmtuaeaISpL"), + Base64.getDecoder().decode("l4lJ2fBE+21MU0L1impmrXOVMXw4d6CpoSLS5Wp66kojeR94cEdUg3JAgkcKyClA"), + Base64.getDecoder().decode("nxPNGpOegXx9wNc4blM250eyYKY+zZ2DGf3Zfp9irTZ7jpzcEO7fb5BAx1YnbTed"), + Base64.getDecoder().decode("7en0qGieNCkyZGT44+/pQbgebgoVWk9527ygAFOy6s3s1+XY/kiOXm6fp9ru/y9r"), + }; + // Requests + final EncryptedRequest[] encryptedRequest = { + new EncryptedRequest( + "D3D82A6B-47CF-4225-BBE5-BAD96FB84CA4", + "AjpBEi1V6hxMt6SXmn6pFuSNd6S2loTKwqa/9A5hL+lh", + "7m3Eh0RUc2S4k1sThtVQvwzK1QEiAJwxAgKmTigAqY3wPen5EO+HJG6FolSVTM0J", + "un7Wreqd91tQp1UuqrKDRwKpCIHn4dxFaD6PEay94tQ=", + "yss0YBlx0ERypDj/4HF6oQ==", + 1723109505418L + ), + new EncryptedRequest( + "1221CD15-9092-4779-A157-04DC229A63F7", + "AjJv5HtX/WOk2ajL186KJ+9GGbYYAsx/kEAcSr7Aot0k", + "/n1ijWx8rY0a9DSd8peAMbEznhyKhSGPDbmRQWwTzLErKdyFCSWMdsfyYjprK/MmYczAoJvSgHhe9FeWvg/aMpGWsykjlaGzprZ/WZT+vMA=", + "jkQZgeHwm2UVgCX3EU/SpBLZcDCoWCqke7PnZgXtz4Y=", + "lGvXPH17WpDErd277D7w1w==", + 1723109505420L + ), + new EncryptedRequest( + "D3D82A6B-47CF-4225-BBE5-BAD96FB84CA4", + "AgGQFxV3lw5VDbHHI6lTdoUOMvA+ciXc+JFI8OsY4ErK", + "Kb0IVdVE5aicv70QY6cfDnE690jVhEqhOct28y1r7G0=", + "mbyD0Z341x6pkXNwhA8Q8DQzP9Pk6E3CkYxJ+7pAauA=", + "L9wCRvnLTUkla7IAlrprEQ==", + 1723109505420L + ), + new EncryptedRequest( + "1221CD15-9092-4779-A157-04DC229A63F7", + "AgjDJvBgQubjJsc3mG/usmz1Saachm56h+L7Ao+ODS+G", + "OnI4x+FwViNe3zACnpkhLib5U8s37EKPYlcp7+EP+0R9EYYkEfQoosyavXMvcULam0TvdixhIt98xWsW6UPrDA==", + "o123KQc+4MLuxG1rlfS/uFVTsChp1mIrwokpIsXeGRE=", + "dYXDUMkh3AcATXwenSdDyg==", + 1723109505421L + ), + new EncryptedRequest( + "1221CD15-9092-4779-A157-04DC229A63F7", + "Aos8e2W2DbLD+rBNA6Mwzj+RWaETuLGo4M/sEdRtRENL", + "z2qMMLBv9dEqvv9SdZpxdoUmvPKBTlQU5MELLivW+2SZyv4cK+yT46cLEM8bdnly1f28/3nYogZaajzftXbZM2Bj8cSYBjZuQRLIbUcjz2wLtWP7BYEAk8LlS+gA3dAOrZ/lWI4MOEt1lgG0JkEHBkEpmD2s3wPSNr9t1fUJqU4=", + "bqA6SQkCfOVf5+5Bt1p6cj5PheYjeGMOb5ynF3oW2Jc=", + "C0t960Q62hxHaWnnu6sYEw==", + 1723109505421L + ), + new EncryptedRequest( + "1221CD15-9092-4779-A157-04DC229A63F7", + "A1Ph49CFAdWfQFlzYPDeaFdipYMJGY+qYWEJgphvE601", + "v5chxkMsHJanOOw/av+oRbPsk2Va226igxQ+2frT3AraTLwJxotHocnTFxyK7pNk", + "0yjA3GDiKJooZMi2hOkkD+aICpY7Slo/nzg0oTYrqJM=", + "EoNe/DqID0Isa15tzFeTYw==", + 1723109505421L + ), + new EncryptedRequest( + "1221CD15-9092-4779-A157-04DC229A63F7", + "A+5Y+goYEAPxnM5xVxLkZoJTSG5SEoa2D6U2/a//+vgS", + "gg9w0km2aG+pchUeHL5BEjDMROOcuTmDSMTBRRf9OyTwrYA6+a991jhdZiSYT6MSK52n2hd6yWvEp18NQI6VOy0gsxAzoOXfYf2Rir9rvtIcmtRC76cYDqLHA9Dl2TyrzacnOSZJRwGOePal1RM8vQ==", + "T9Y0jFGSzIsZ0YWmSZ3D4JpDP8W18ksPMIb0obUAUiM=", + "nt9/rGJ74UoCKT24QS+USw==", + 1723109505422L + ), + new EncryptedRequest( + "D3D82A6B-47CF-4225-BBE5-BAD96FB84CA4", + "A7MzuALkFpmLMUOoPfXyx+aCAKZqP0V1RnRLNKbqrCdn", + "xaMGsBQgJ5NihO8GGrjG1epaEszSDcv8Z67WBJy0olQ5sfrlx+nR112JAKIKqpDo4DApF9EOkDfi5za0DnlryvGPpiaLbngbF06QR85DFNkOUD5Gt/DuN/qbGdHYJ66AsZhAdUf8L0u5OGYbYF6ULQ==", + "hkLthp5Eti8L/EMksBU5eeJSpxAUHVZ9X/59ROyo3uE=", + "af7JpUq2cwR0Ekodu6WQQQ==", + 1723109505422L + ), + new EncryptedRequest( + "1221CD15-9092-4779-A157-04DC229A63F7", + "AyAZz2budSXg9tUr41qMRIWZYHvf8ZRg1Ky1xXfjUVzP", + "P1E456VYswsieUXDxi49WldA647JbSy5YfwS6xoJijWZ7/ml3Zx5VMJYz+X8X9Wm2+GNiyWiLURpJaTMK3lwXOEFUWUDoP0cv6du+Vz7jQgoyPvgSxpcOeb9NEiOcbgc", + "MrFSFDaBZA1sDibSzT9Si+4blDj7q5Op33FfnYFwlzo=", + "o4KfZWSYNqBjwaHqJcwYTg==", + 1723109505422L + ), + new EncryptedRequest( + "D3D82A6B-47CF-4225-BBE5-BAD96FB84CA4", + "A6tOYHM9zg9O4v/rTAiduPRfJgWLT47V/1SKVpOVfb3h", + "6E5yo1+y/Nv9A9uTr2dWijEAoOMOlCX39fdCDE5ohbBw6slMbFBIC6HUn7qBs8dBgMNJTatJEp/twGJZyaT6+WMOZRI7ec7/bOImrN9kjwkYq70gY/UHPETUyBkczYc+", + "1j6ULk0WucfGFjiN9T7oGykuh0BriYv3Y0y/FK7X+hw=", + "/KUGtLbpCgqW+KyTfP/1FQ==", + 1723109505423L + ), + new EncryptedRequest( + "1221CD15-9092-4779-A157-04DC229A63F7", + "Ajqbv+0CUuWHZQuiU1d+Z8x4sbXDB37sm0Kbjp95kzPI", + "OKr4ceWyBbLTxzZhv5RQvlG44K+n+ohw4JUbV30lC0KIypNl0uKwdzSQtK5eljKXdfYxaLSuY+Gwj/NK+xdQkdMXskLeXluey5GET23HaL4=", + "048mD+C38ojf0M0CpEU/uLuZbRLlZVFfzCCK/2f0+KI=", + "K+XqUGF5lUKgTz0yaJ9p2g==", + 1723109505423L + ), + new EncryptedRequest( + "1221CD15-9092-4779-A157-04DC229A63F7", + "A3uO4rYlQByC4ch5ylQEgFwOqYVANPLPw61DzbmT2nwH", + "VnYlfhQVaYFkCCvG6snx6bgGbHbNqS69AnBvcJ7o+vVtqtaZ13XaXWHCM3cyKW70QZs5uGuI/NWHD9pItXQpaxGkogmlixNc/EOpk7FJv04x1+SqKDFDveZgeORIFcOqX10V9BmhoqoBodUQ/Mf/19zc3/hXL6B2Py9MwnBlfxE=", + "YerKe/F5zFLkK52ebcwpcMxf3ZAmnGO+hWgBYk863UU=", + "HadtUun2ZzG8yY9ZdoMieg==", + 1723109505423L + ), + new EncryptedRequest( + "1221CD15-9092-4779-A157-04DC229A63F7", + "Arn/DbG8zpduSRv5WazPO14rRicFGzzSruSeK91TzLcz", + "Hy6BkHDntqmbV56oNTL+7aIJloEtkiZkiDZOmaxtsZQPGh2ZOcdL58M29mX0SCJ5uWEIKiQMGARtRNef4K9/ZyiKV3VdJFkzXKKs3ul5d+w=", + "5hu/DaxE7c74Pv0abvafGTi1pET/2zUaOA6QDAaRlMY=", + "z6lNafKqRONRBYwT6mfZHQ==", + 1723109505424L + ), + new EncryptedRequest( + "1221CD15-9092-4779-A157-04DC229A63F7", + "A2dQMe2lT6PNXju5qnY58dc7MrVlfeMxvmHpYZVSo1iy", + "yFi4XJ0kADIbf6xL4pShHhsAdDhmLyiHuf2uDVmGTsQDeDunVLn9E/cPOY3Pi8beTfyLMTuJs/KCYacDXkniCmzuawsftmASF14Ee2nLfUZoBhdA2HUDdKiIy+zvfrSChRx9YP0gkXE5bMRFpWgLmQ==", + "+MHylKbS+wVabW1ASOTyrVgHiSYtD7QeIP/mjWG0U8c=", + "xei7+wZwpJnRVnhsjRAEpg==", + 1723109505424L + ), + new EncryptedRequest( + "D3D82A6B-47CF-4225-BBE5-BAD96FB84CA4", + "Ai7rf1nkviyd/H4oLwjazip5ceScgTyV+B3F/GqQblen", + "ZYxobd3H7Uj1VUQQvlh+7PBBzmtCPoVKDde5rjRbHx+10WRCFjV5Uhb3ySHWLuXUrqDmTGERRDEmPNXcfkp9Sw==", + "34Xcv3x1DVaNAsDnRyBCKynDmSVgzSaI3tAWWRKU1gs=", + "34OaEzc8gcHw/TDsr5hI+A==", + 1723109505424L + ), + new EncryptedRequest( + "1221CD15-9092-4779-A157-04DC229A63F7", + "Awe+CP/SBxK4U8Szk4/2mJEI+k5J0t1Iul1FTNBNdG4K", + "Im5FJi42sIoKKuRQwyKaX/nGsRWDeDXNpE6jTyXmKENm/ulBftYmWCsDhX8uJKSi3ICtN70JtbNdOcWG+KsVAw==", + "kfqKaModZjh98LCMNOHyVdu2jr+zqIjq8Y185iTz9Qw=", + "5YS/q6v60vqPzZwW/TqOhg==", + 1723109505425L + ), + }; + // Responses + final EncryptedResponse[] encryptedResponse = { + new EncryptedResponse( + "VKUZve03Rc+8N2D2YzGeX9ZZteeQws9ZAW7N2VVZ4cj8YHpHf+X4ULpqYeGKCHfJXi4Dvt6ZbbAU4i7rImvmRH7ZdMZgyVMlsRXwyJxIhDgkr8zLQlJDJ3Nc/TL2n2YTw3ukL2vv3ZW65UcDOWi9OBnXuEFYvuAjGR7zJLDL8Z0=", + "ebBjC2k7LndYqgOgbE239Rc1yhhRRhOGL/QGk23P458=", + "mrL2R2ochtK1QFfLi9dX3Q==", + 1723109505420L + ), + new EncryptedResponse( + "qxbAsh4KlTWrfoRb2f65FUkBMfvPjJdPkc5z44rdNJ7angP/q83NTw19XurQ8N1RjA06ozqnOR4pr9KrjuWq38kyVEWEsrMsrE2rLjzcVqyoFNOBd3tPK74f/uLmbVFnqbUoKaqjn4mBIHCfgWle7g==", + "GMeP0BM62NDRxWBtHMsadAHQQzsgmfZfGU3x9piipfM=", + "beYoMVodt06E7yk2WMFiCA==", + 1723109505420L + ), + new EncryptedResponse( + "l+Yl3JfRpcr+ReXSDdTo2GVbe+c98rpfX3vODqnrpkk=", + "cRPSf7+3IA8M1zjQnGEixuFlJ5O6hsmzvWeB2xFHfCI=", + "qPtFVgDgtgJpNTzuElDoVA==", + 1723109505421L + ), + new EncryptedResponse( + "Y8KAD1G9wUpoTXpA0UKMI4PaUgS43uUFrOTBR3cCoBUdOWS4HizPdF+3SxdkbP5Z", + "QfQzM+0z0re6/AWMNOI8uP7syAeCtud+TkDt+H1X/tM=", + "A/+VbdsF+0s8HvJrBAtBCQ==", + 1723109505421L + ), + new EncryptedResponse( + "+Jqs/d97p0Qau9ixhL23cctRnUwowZuTzvA3MHsBH24=", + "AgBS0dF5RSfPlvbqgtFpMwj2QSDQUXIUcZdNUyJPzO0=", + "iu0blftcv9NCHb0mJVqRKA==", + 1723109505421L + ), + new EncryptedResponse( + "jKg+rY99pZ3gZa+h5Dfy7ohbhKKUIhKWltXrx8Az4DTyRiT8PfljuUKWD1nXYtpToAodYrI83scJ5OuoOILcxQ7/h3fLHs6KB642xaoV/od4eVMYoXqDXMraMojCsxCJ", + "8YJ8n79aFpOAawRnSfG7XlNYNdGVfP2iGKhrE2VP0ho=", + "qD/LMXJEWu8/64ZVLs3+7g==", + 1723109505422L + ), + new EncryptedResponse( + "Od0g66R5gHPqyLjaKYkiSyKg11qzpMERanBS3qlSJ13MIArCWQWgq54408xvo1hpt5V8Wgj7ITwfsJ8+AQTZOgx7Wz3a1x56x8X7ooZhIk8=", + "ndfN2p7RMwWo6JDS4ifa5kleEW8CcBjjwySh67niVZo=", + "vywPr8XZ8b2YyDtHMikmfg==", + 1723109505422L + ), + new EncryptedResponse( + "3GGQRP4u4+w/d7/KtPS8SjDa8lV7AxZhXbJKzKWwx80=", + "irvrHy2xNLjDfAeL/4dxmmSCuuDsOxXHCc95P/i/35E=", + "BMWmr4DsI8+WImCDvwB2/w==", + 1723109505422L + ), + new EncryptedResponse( + "tfMDn6+5V1Zppc4huevk3LI/dgzOuSRTYqtXJf+xB/hNzNc2hChinWIjKMh2cdWwoms3WO+boaKGnCDdVbSCDEx+nFg6T4iN6rfz4qTwaov6KdLkT04Y8hnkbi4YAyNm", + "90Vud5c9q8Xy+UgMGtq5D6vPs5Hsn0Nkmj+rUmuUcz8=", + "YNJifcT945fhcKm3aqkhag==", + 1723109505423L + ), + new EncryptedResponse( + "0fWvysKeg3naheL/A5cJjTiA+BmhZYbDkHVK63JPosXDhqZzqPrJ0/KvPE116ELpG2FzQP5LnD0Jk9eJ627p67nMhJD+jQkRFQgqKeggViiw+zEsQtp/dcIN3ZpdR+zh", + "TIe67QK7kYFlMI7tEMB5+DdqwVdAUNbje/xVyrLEwwI=", + "LdNF+2cVBklgSNtd8VgVHQ==", + 1723109505423L + ), + new EncryptedResponse( + "WKwK5/O9ebjhrec16gMbS5tuAiYSE7/7oxMRc+DU8ZU6FSNUewK8O0cVOV3sT6++6U3QgPJLbgRIBP6lZjvAUcrzXlwjNjQJEmO3816BOo8=", + "Eo0IFaMj5O9ZPfq5DCqS+6m0swuEGgoVfihAKtDTnsg=", + "miiZTny2CvOrBZkjD+eaLA==", + 1723109505423L + ), + new EncryptedResponse( + "jDmIvPflnOKjS45+cSCqaA==", + "h39gAppf4ooZoh3DlXUTg8K6hMvTeUDXjJIbrbEKefg=", + "G68hARhQVl/NlWqvqdrHAw==", + 1723109505424L + ), + new EncryptedResponse( + "JCeEIhe8hUKPbb0+FB/s1A==", + "1ZYXTaUXg8BH37PHNUYZC/qAaiu72vvbBUMMayO5ygc=", + "v4k9JUEQqmqs0avfakFRiQ==", + 1723109505424L + ), + new EncryptedResponse( + "lYITkSdxBpjIKd6YsORWZLKE21G3bbRSd+7/7CeSk0jXrtAnoyqvYfvcdx2TVtOVOlM8yAkgwuDn610ovcDW9mT5/HfvdoB1c7v8uwXwSEorpajFTT/b6tYo4fRD+lGt", + "8/r/tlMCzmHLwszOGUwBGGK9MM1Jis2R8Gmk4e17AJo=", + "WGeBG1GE8gFWSXQCUR9dKQ==", + 1723109505424L + ), + new EncryptedResponse( + "it9d1VO49uCf4G3zax9Z0IxNmTaoUb2aVHZB45b8rmd/myB8pjEhvzowwatdx5fX", + "EmyVIkCwUqH0SCRxqHWDXIjZhB23uaxLFozdlzB8f7U=", + "XAqO+IzvrQ6zsEyHQd2pyg==", + 1723109505425L + ), + new EncryptedResponse( + "pDks/WpNZ3l71+1vgVQReVIjlSC5o7Jyepka/kbj5oUqtjyO3WopHyfAB7e1exqDl6dLDwsP0TcIndKmAPPdpQ==", + "Ob1ku/gu4dFdov1GVZIRZ8dSGeh2Kt8JbFACi/k5onc=", + "9/QPax/kk/VO5mto3ufdBA==", + 1723109505425L + ), + }; + // ---------------------------- + // Start of test + + for (int i = 0; i < encryptedRequest.length; i++) { + // Prepare values for this batch + final EncryptedRequest request = encryptedRequest[i]; + final EncryptedResponse response = encryptedResponse[i]; + final EncryptorId eid = encryptorIds[i]; + final EncryptorScope scope = eid.scope(); + final byte[] sharedInfo1 = eid.getEciesSharedInfo1("3.3"); + final byte[] appSecret = applicationSecret.getBytes(StandardCharsets.UTF_8); + final byte[] envelopeKey = envelopeKeys[i]; + + // Construct Server's encryptor + final ServerEncryptor serverEncryptor; + if (scope == EncryptorScope.APPLICATION_SCOPE) { + serverEncryptor = encryptorFactory.getServerEncryptor(eid, + new EncryptorParameters("3.3", applicationKey, null, tempKeyIdApplication), + new ServerEncryptorSecrets(masterServerPrivateKey, applicationSecret) + ); + } else { + serverEncryptor = encryptorFactory.getServerEncryptor(eid, + new EncryptorParameters("3.3", applicationKey, activationId, tempKeyIdActivation), + new ServerEncryptorSecrets(serverPrivateKey, applicationSecret, transportKey) + ); + } + // Decrypt request and compare to the expected value. + final byte[] decryptedRequestData = serverEncryptor.decryptRequest(request); + assertArrayEquals(plainRequestData[i], decryptedRequestData); + } + } /** * Construct EncryptorParameters for given encryptor and protocol version. @@ -910,9 +1339,11 @@ public void testVectors_3_2() throws Exception { */ private EncryptorParameters getParametersForEncryptor(EncryptorId encryptorId, String protocolVersion) { if (encryptorId.scope() == EncryptorScope.ACTIVATION_SCOPE) { - return new EncryptorParameters(protocolVersion, configuration.applicationKey, configuration.activationId); + final String tempKeyId = "3.3".equals(protocolVersion) ? configuration.tempKeyActivation : null; + return new EncryptorParameters(protocolVersion, configuration.applicationKey, configuration.activationId, tempKeyId); } else { - return new EncryptorParameters(protocolVersion, configuration.applicationKey, null); + final String tempKeyId = "3.3".equals(protocolVersion) ? configuration.tempKeyApplication : null; + return new EncryptorParameters(protocolVersion, configuration.applicationKey, null, tempKeyId); } } @@ -925,7 +1356,7 @@ private EncryptorParameters getParametersForEncryptor(EncryptorId encryptorId, S */ private EncryptorSecrets getClientSecrets(EncryptorId encryptorId, String protocolVersion) throws Exception { final boolean appScope = encryptorId.scope() == EncryptorScope.APPLICATION_SCOPE; - if ("3.0".equals(protocolVersion) || "3.1".equals(protocolVersion) || "3.2".equals(protocolVersion)) { + if ("3.0".equals(protocolVersion) || "3.1".equals(protocolVersion) || "3.2".equals(protocolVersion) || "3.3".equals(protocolVersion)) { return new ClientEncryptorSecrets( appScope ? configuration.keyMasterServer.getPublic() : configuration.keyServer.getPublic(), configuration.applicationSecret, @@ -944,7 +1375,7 @@ private EncryptorSecrets getClientSecrets(EncryptorId encryptorId, String protoc */ private EncryptorSecrets getServerSecrets(EncryptorId encryptorId, String protocolVersion) throws Exception { final boolean appScope = encryptorId.scope() == EncryptorScope.APPLICATION_SCOPE; - if ("3.0".equals(protocolVersion) || "3.1".equals(protocolVersion) || "3.2".equals(protocolVersion)) { + if ("3.0".equals(protocolVersion) || "3.1".equals(protocolVersion) || "3.2".equals(protocolVersion) || "3.3".equals(protocolVersion)) { return new ServerEncryptorSecrets( appScope ? configuration.keyMasterServer.getPrivate() : configuration.keyServer.getPrivate(), configuration.applicationSecret, diff --git a/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/signature/PowerAuthSignatureFormatTest.java b/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/signature/PowerAuthSignatureFormatTest.java index cb7dfa50a..2130bfb17 100644 --- a/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/signature/PowerAuthSignatureFormatTest.java +++ b/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/signature/PowerAuthSignatureFormatTest.java @@ -34,6 +34,7 @@ public void testValidVersions() throws Exception { assertEquals(PowerAuthSignatureFormat.DECIMAL, PowerAuthSignatureFormat.getFormatForSignatureVersion("3.0")); assertEquals(PowerAuthSignatureFormat.BASE64, PowerAuthSignatureFormat.getFormatForSignatureVersion("3.1")); assertEquals(PowerAuthSignatureFormat.BASE64, PowerAuthSignatureFormat.getFormatForSignatureVersion("3.2")); + assertEquals(PowerAuthSignatureFormat.BASE64, PowerAuthSignatureFormat.getFormatForSignatureVersion("3.3")); assertEquals(PowerAuthSignatureFormat.BASE64, PowerAuthSignatureFormat.getFormatForSignatureVersion("4.0")); } diff --git a/powerauth-java-http/src/main/java/io/getlime/security/powerauth/http/PowerAuthEncryptionHttpHeader.java b/powerauth-java-http/src/main/java/io/getlime/security/powerauth/http/PowerAuthEncryptionHttpHeader.java index 6c11ba723..886b16118 100644 --- a/powerauth-java-http/src/main/java/io/getlime/security/powerauth/http/PowerAuthEncryptionHttpHeader.java +++ b/powerauth-java-http/src/main/java/io/getlime/security/powerauth/http/PowerAuthEncryptionHttpHeader.java @@ -148,4 +148,5 @@ public String getActivationId() { public String getVersion() { return version; } + } diff --git a/powerauth-java-http/src/main/java/io/getlime/security/powerauth/http/validator/ValueTypeValidator.java b/powerauth-java-http/src/main/java/io/getlime/security/powerauth/http/validator/ValueTypeValidator.java index 0af47f8af..ff7266360 100644 --- a/powerauth-java-http/src/main/java/io/getlime/security/powerauth/http/validator/ValueTypeValidator.java +++ b/powerauth-java-http/src/main/java/io/getlime/security/powerauth/http/validator/ValueTypeValidator.java @@ -51,7 +51,7 @@ public class ValueTypeValidator { /** * Admissible protocol versions in the header. */ - private static final Set PROTOCOL_VERSIONS = Set.of("3.2", "3.1", "3.0"); + private static final Set PROTOCOL_VERSIONS = Set.of("3.3", "3.2", "3.1", "3.0"); /** * Admissible signature types in the header.