From 390e539b541612634ff9d229c7719c17f2002570 Mon Sep 17 00:00:00 2001 From: Samin Rahman Date: Thu, 8 Jan 2026 14:58:08 +1100 Subject: [PATCH 1/9] Added ACCP Provider and ecdh caching --- Dockerfile | 2 + pom.xml | 8 ++++ .../operator/vertx/UIDOperatorVerticle.java | 40 ++++++++++++++++++- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index b9e031d64..7c0aa5087 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,8 @@ # sha from https://hub.docker.com/layers/library/eclipse-temurin/21.0.9_10-jre-alpine-3.23/images/sha256-f599f6fa11f007b6dcf6e85ec2c372c1eba2b6940a7828eb6e665665ea5edd1c FROM eclipse-temurin@sha256:243e711289b0f17e05a4df60454bbb1b8ed7b126db4de2d5535da994b7417111 +RUN apk add --no-cache gcompat + WORKDIR /app EXPOSE 8080 diff --git a/pom.xml b/pom.xml index a214ac523..81022ae44 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,7 @@ com.uid2.operator.vertx.UIDOperatorVerticle 1.12.2 + 2.3.3 2.1.6 2.1.0 2.1.19 @@ -203,6 +204,13 @@ 5.12.0 test + + + software.amazon.cryptools + AmazonCorrettoCryptoProvider + ${accp.version} + linux-x86_64 + diff --git a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java index fd11f4882..7e7643856 100644 --- a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java +++ b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java @@ -91,6 +91,42 @@ public class UIDOperatorVerticle extends AbstractVerticle { private static final ObjectMapper OBJECT_MAPPER = Mapper.getApiInstance(); private static final long SECOND_IN_MILLIS = 1000; + // ECDH provider selection: tries ACCP first, falls back to default (SunEC) + private static final String ECDH_PROVIDER_NAME = initEcdhProvider(); + private static final ThreadLocal THREAD_LOCAL_KEY_AGREEMENT = ThreadLocal.withInitial(() -> { + try { + return createKeyAgreement(); + } catch (NoSuchAlgorithmException | NoSuchProviderException e) { + throw new RuntimeException("Failed to create KeyAgreement", e); + } + }); + + private static String initEcdhProvider() { + // Try ACCP (Amazon Corretto Crypto Provider) first + try { + KeyAgreement ka = KeyAgreement.getInstance("ECDH", "AmazonCorrettoCryptoProvider"); + LOGGER.info("ECDH using AmazonCorrettoCryptoProvider"); + return "AmazonCorrettoCryptoProvider"; + } catch (NoSuchAlgorithmException | NoSuchProviderException e) { + // ACCP not available, fall through + } + + // Fall back to default provider (SunEC on most JDKs) + LOGGER.info("ECDH using default provider (SunEC)"); + return null; + } + + private static KeyAgreement createKeyAgreement() throws NoSuchAlgorithmException, NoSuchProviderException { + if (ECDH_PROVIDER_NAME != null) { + return KeyAgreement.getInstance("ECDH", ECDH_PROVIDER_NAME); + } + return KeyAgreement.getInstance("ECDH"); + } + + private static KeyAgreement getKeyAgreement() { + return THREAD_LOCAL_KEY_AGREEMENT.get(); + } + private static final String REQUEST = "request"; private final HealthComponent healthComponent = HealthManager.instance.registerComponent("http-server"); private final Cipher aesGcm; @@ -408,8 +444,8 @@ private void handleClientSideTokenGenerateImpl(RoutingContext rc) throws NoSuchA return; } - // Perform key agreement - final KeyAgreement ka = KeyAgreement.getInstance("ECDH"); + // Perform key agreement (uses cached provider: ACCP > Conscrypt > SunEC) + final KeyAgreement ka = getKeyAgreement(); ka.init(clientSideKeypair.getPrivateKey()); ka.doPhase(clientPublicKey, true); From 6139317f29cd4ddabe24fbc82146e9f09129da6d Mon Sep 17 00:00:00 2001 From: Samin Rahman Date: Fri, 9 Jan 2026 15:46:57 +1100 Subject: [PATCH 2/9] Moved crypto code to a service and updated ACCP --- Dockerfile | 6 ++- pom.xml | 2 +- .../service/CryptoProviderService.java | 50 +++++++++++++++++++ .../operator/vertx/UIDOperatorVerticle.java | 40 +-------------- 4 files changed, 58 insertions(+), 40 deletions(-) create mode 100644 src/main/java/com/uid2/operator/service/CryptoProviderService.java diff --git a/Dockerfile b/Dockerfile index 7c0aa5087..9281a7dc8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # sha from https://hub.docker.com/layers/library/eclipse-temurin/21.0.9_10-jre-alpine-3.23/images/sha256-f599f6fa11f007b6dcf6e85ec2c372c1eba2b6940a7828eb6e665665ea5edd1c -FROM eclipse-temurin@sha256:243e711289b0f17e05a4df60454bbb1b8ed7b126db4de2d5535da994b7417111 +FROM eclipse-temurin@sha256:89517925fa675c6c4b770bee7c44d38a7763212741b0d6fca5a5103caab21a97 RUN apk add --no-cache gcompat @@ -20,12 +20,16 @@ COPY ./target/${JAR_NAME}-${JAR_VERSION}-static.tar.gz /app/static.tar.gz COPY ./conf/default-config.json /app/conf/ COPY ./conf/*.xml /app/conf/ +# Fix CVE-2025-68973: Update gnupg to patched version +RUN apk update && apk upgrade gnupg && rm -rf /var/cache/apk/* + RUN tar xzvf /app/static.tar.gz --no-same-owner --no-same-permissions && rm -f /app/static.tar.gz RUN adduser -D uid2-operator && mkdir -p /opt/uid2 && chmod 777 -R /opt/uid2 && mkdir -p /app && chmod 705 -R /app && mkdir -p /app/file-uploads && chmod 777 -R /app/file-uploads && mkdir -p /app/pod_terminating && chmod 777 -R /app/pod_terminating USER uid2-operator CMD java \ + -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints \ -XX:MaxRAMPercentage=95 -XX:-UseCompressedOops -XX:+PrintFlagsFinal -XX:-OmitStackTraceInFastThrow \ -Djava.security.egd=file:/dev/./urandom \ -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.SLF4JLogDelegateFactory \ diff --git a/pom.xml b/pom.xml index 81022ae44..d51e3c184 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ com.uid2.operator.vertx.UIDOperatorVerticle 1.12.2 - 2.3.3 + 2.5.0 2.1.6 2.1.0 2.1.19 diff --git a/src/main/java/com/uid2/operator/service/CryptoProviderService.java b/src/main/java/com/uid2/operator/service/CryptoProviderService.java new file mode 100644 index 000000000..6f81d3442 --- /dev/null +++ b/src/main/java/com/uid2/operator/service/CryptoProviderService.java @@ -0,0 +1,50 @@ +package com.uid2.operator.service; + +import com.uid2.operator.vertx.UIDOperatorVerticle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.crypto.KeyAgreement; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; + +public class CryptoProviderService { + private static final Logger LOGGER = LoggerFactory.getLogger(CryptoProviderService.class); + + // ECDH provider selection: tries ACCP first, falls back to default (SunEC) + private static final String ECDH_PROVIDER_NAME = initEcdhProvider(); + private static final ThreadLocal THREAD_LOCAL_KEY_AGREEMENT = ThreadLocal.withInitial(() -> { + try { + return createKeyAgreement(); + } catch (NoSuchAlgorithmException | NoSuchProviderException e) { + throw new RuntimeException("Failed to create KeyAgreement", e); + } + }); + + private static String initEcdhProvider() { + // Try ACCP (Amazon Corretto Crypto Provider) first + try { + KeyAgreement ka = KeyAgreement.getInstance("ECDH", "AmazonCorrettoCryptoProvider"); + LOGGER.info("ECDH using AmazonCorrettoCryptoProvider"); + return "AmazonCorrettoCryptoProvider"; + } catch (NoSuchAlgorithmException | NoSuchProviderException e) { + // ACCP not available, fall through + LOGGER.info("AmazonCorrettoCryptoProvider is not available"); + } + + // Fall back to default provider (SunEC on most JDKs) + LOGGER.info("ECDH using default provider (SunEC)"); + return null; + } + + private static KeyAgreement createKeyAgreement() throws NoSuchAlgorithmException, NoSuchProviderException { + if (ECDH_PROVIDER_NAME != null) { + return KeyAgreement.getInstance("ECDH", ECDH_PROVIDER_NAME); + } + return KeyAgreement.getInstance("ECDH"); + } + + public static KeyAgreement getKeyAgreement() { + return THREAD_LOCAL_KEY_AGREEMENT.get(); + } +} diff --git a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java index 7e7643856..ce36faf8d 100644 --- a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java +++ b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java @@ -91,42 +91,6 @@ public class UIDOperatorVerticle extends AbstractVerticle { private static final ObjectMapper OBJECT_MAPPER = Mapper.getApiInstance(); private static final long SECOND_IN_MILLIS = 1000; - // ECDH provider selection: tries ACCP first, falls back to default (SunEC) - private static final String ECDH_PROVIDER_NAME = initEcdhProvider(); - private static final ThreadLocal THREAD_LOCAL_KEY_AGREEMENT = ThreadLocal.withInitial(() -> { - try { - return createKeyAgreement(); - } catch (NoSuchAlgorithmException | NoSuchProviderException e) { - throw new RuntimeException("Failed to create KeyAgreement", e); - } - }); - - private static String initEcdhProvider() { - // Try ACCP (Amazon Corretto Crypto Provider) first - try { - KeyAgreement ka = KeyAgreement.getInstance("ECDH", "AmazonCorrettoCryptoProvider"); - LOGGER.info("ECDH using AmazonCorrettoCryptoProvider"); - return "AmazonCorrettoCryptoProvider"; - } catch (NoSuchAlgorithmException | NoSuchProviderException e) { - // ACCP not available, fall through - } - - // Fall back to default provider (SunEC on most JDKs) - LOGGER.info("ECDH using default provider (SunEC)"); - return null; - } - - private static KeyAgreement createKeyAgreement() throws NoSuchAlgorithmException, NoSuchProviderException { - if (ECDH_PROVIDER_NAME != null) { - return KeyAgreement.getInstance("ECDH", ECDH_PROVIDER_NAME); - } - return KeyAgreement.getInstance("ECDH"); - } - - private static KeyAgreement getKeyAgreement() { - return THREAD_LOCAL_KEY_AGREEMENT.get(); - } - private static final String REQUEST = "request"; private final HealthComponent healthComponent = HealthManager.instance.registerComponent("http-server"); private final Cipher aesGcm; @@ -444,8 +408,8 @@ private void handleClientSideTokenGenerateImpl(RoutingContext rc) throws NoSuchA return; } - // Perform key agreement (uses cached provider: ACCP > Conscrypt > SunEC) - final KeyAgreement ka = getKeyAgreement(); + // Perform key agreement (uses cached provider: ACCP > SunEC) + final KeyAgreement ka = CryptoProviderService.getKeyAgreement(); ka.init(clientSideKeypair.getPrivateKey()); ka.doPhase(clientPublicKey, true); From 7d2de01982b111e83292556844dc00140861dda4 Mon Sep 17 00:00:00 2001 From: Release Workflow Date: Fri, 9 Jan 2026 04:50:01 +0000 Subject: [PATCH 3/9] [CI Pipeline] Released Snapshot version: 5.63.6-alpha-280-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d51e3c184..c0ff61fa9 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.uid2 uid2-operator - 5.63.5 + 5.63.6-alpha-280-SNAPSHOT UTF-8 From e14fc39fb0c6c2cfabaf17ff32af888b35c6dd80 Mon Sep 17 00:00:00 2001 From: Samin Rahman Date: Fri, 9 Jan 2026 16:28:32 +1100 Subject: [PATCH 4/9] Load in ACCP provider --- .../service/CryptoProviderService.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/uid2/operator/service/CryptoProviderService.java b/src/main/java/com/uid2/operator/service/CryptoProviderService.java index 6f81d3442..b656e3355 100644 --- a/src/main/java/com/uid2/operator/service/CryptoProviderService.java +++ b/src/main/java/com/uid2/operator/service/CryptoProviderService.java @@ -1,12 +1,13 @@ package com.uid2.operator.service; -import com.uid2.operator.vertx.UIDOperatorVerticle; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import software.amazon.cryptools.AmazonCorrettoCryptoProvider; import javax.crypto.KeyAgreement; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; +import java.security.Security; public class CryptoProviderService { private static final Logger LOGGER = LoggerFactory.getLogger(CryptoProviderService.class); @@ -24,15 +25,19 @@ public class CryptoProviderService { private static String initEcdhProvider() { // Try ACCP (Amazon Corretto Crypto Provider) first try { - KeyAgreement ka = KeyAgreement.getInstance("ECDH", "AmazonCorrettoCryptoProvider"); - LOGGER.info("ECDH using AmazonCorrettoCryptoProvider"); - return "AmazonCorrettoCryptoProvider"; - } catch (NoSuchAlgorithmException | NoSuchProviderException e) { - // ACCP not available, fall through - LOGGER.info("AmazonCorrettoCryptoProvider is not available"); + // Add ACCP at lowest priority so it doesn't become default for other algorithms + Security.addProvider(AmazonCorrettoCryptoProvider.INSTANCE); + + // Verify it works for ECDH + KeyAgreement ka = KeyAgreement.getInstance("ECDH", AmazonCorrettoCryptoProvider.PROVIDER_NAME); + LOGGER.info("ECDH using AmazonCorrettoCryptoProvider (added at lowest priority)"); + return AmazonCorrettoCryptoProvider.PROVIDER_NAME; + } catch (Throwable e) { + // ACCP not available + LOGGER.info("AmazonCorrettoCryptoProvider is not available: {}", e.getMessage()); } - // Fall back to default provider (SunEC on most JDKs) + // Fall back to default provider LOGGER.info("ECDH using default provider (SunEC)"); return null; } From 0afcc435d6f01e5ecd77a0c5586f37b3b1123d6d Mon Sep 17 00:00:00 2001 From: Samin Rahman Date: Fri, 9 Jan 2026 16:31:00 +1100 Subject: [PATCH 5/9] Fixed incorrect imports --- .../java/com/uid2/operator/service/CryptoProviderService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/uid2/operator/service/CryptoProviderService.java b/src/main/java/com/uid2/operator/service/CryptoProviderService.java index b656e3355..bbc5290ae 100644 --- a/src/main/java/com/uid2/operator/service/CryptoProviderService.java +++ b/src/main/java/com/uid2/operator/service/CryptoProviderService.java @@ -2,7 +2,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import software.amazon.cryptools.AmazonCorrettoCryptoProvider; +import com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider; import javax.crypto.KeyAgreement; import java.security.NoSuchAlgorithmException; From e530d6c2ed39d06a32a6aad478e6aaadfdfc543d Mon Sep 17 00:00:00 2001 From: Release Workflow Date: Fri, 9 Jan 2026 05:36:01 +0000 Subject: [PATCH 6/9] [CI Pipeline] Released Snapshot version: 5.63.7-alpha-281-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c0ff61fa9..1b62f56b5 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.uid2 uid2-operator - 5.63.6-alpha-280-SNAPSHOT + 5.63.7-alpha-281-SNAPSHOT UTF-8 From b3e8b8b3347cf01f46c39b968bb824119adb9887 Mon Sep 17 00:00:00 2001 From: Samin Rahman Date: Mon, 12 Jan 2026 10:17:39 +1100 Subject: [PATCH 7/9] Reverted Dockerfile to remove JFR flags --- Dockerfile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9281a7dc8..7c0aa5087 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # sha from https://hub.docker.com/layers/library/eclipse-temurin/21.0.9_10-jre-alpine-3.23/images/sha256-f599f6fa11f007b6dcf6e85ec2c372c1eba2b6940a7828eb6e665665ea5edd1c -FROM eclipse-temurin@sha256:89517925fa675c6c4b770bee7c44d38a7763212741b0d6fca5a5103caab21a97 +FROM eclipse-temurin@sha256:243e711289b0f17e05a4df60454bbb1b8ed7b126db4de2d5535da994b7417111 RUN apk add --no-cache gcompat @@ -20,16 +20,12 @@ COPY ./target/${JAR_NAME}-${JAR_VERSION}-static.tar.gz /app/static.tar.gz COPY ./conf/default-config.json /app/conf/ COPY ./conf/*.xml /app/conf/ -# Fix CVE-2025-68973: Update gnupg to patched version -RUN apk update && apk upgrade gnupg && rm -rf /var/cache/apk/* - RUN tar xzvf /app/static.tar.gz --no-same-owner --no-same-permissions && rm -f /app/static.tar.gz RUN adduser -D uid2-operator && mkdir -p /opt/uid2 && chmod 777 -R /opt/uid2 && mkdir -p /app && chmod 705 -R /app && mkdir -p /app/file-uploads && chmod 777 -R /app/file-uploads && mkdir -p /app/pod_terminating && chmod 777 -R /app/pod_terminating USER uid2-operator CMD java \ - -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints \ -XX:MaxRAMPercentage=95 -XX:-UseCompressedOops -XX:+PrintFlagsFinal -XX:-OmitStackTraceInFastThrow \ -Djava.security.egd=file:/dev/./urandom \ -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.SLF4JLogDelegateFactory \ From d210d417e166cae44d64dd4977d742077643f298 Mon Sep 17 00:00:00 2001 From: Samin Rahman Date: Mon, 12 Jan 2026 12:09:10 +1100 Subject: [PATCH 8/9] Added macos binaries for ACCP --- pom.xml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1b62f56b5..23a00d882 100644 --- a/pom.xml +++ b/pom.xml @@ -204,13 +204,26 @@ 5.12.0 test - + + software.amazon.cryptools AmazonCorrettoCryptoProvider ${accp.version} linux-x86_64 + + software.amazon.cryptools + AmazonCorrettoCryptoProvider + ${accp.version} + osx-x86_64 + + + software.amazon.cryptools + AmazonCorrettoCryptoProvider + ${accp.version} + osx-aarch_64 + From 0bb68909eee03c7f467040f94cb3eceff176617a Mon Sep 17 00:00:00 2001 From: Samin Rahman Date: Mon, 12 Jan 2026 14:08:28 +1100 Subject: [PATCH 9/9] Removed threadlocal caching and added CryptoProvider to tests --- .../service/CryptoProviderService.java | 19 ++++++------------- .../operator/vertx/UIDOperatorVerticle.java | 2 +- .../ClientSideTokenGenerateTestUtil.java | 4 +++- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/uid2/operator/service/CryptoProviderService.java b/src/main/java/com/uid2/operator/service/CryptoProviderService.java index bbc5290ae..68f5d6acd 100644 --- a/src/main/java/com/uid2/operator/service/CryptoProviderService.java +++ b/src/main/java/com/uid2/operator/service/CryptoProviderService.java @@ -14,13 +14,6 @@ public class CryptoProviderService { // ECDH provider selection: tries ACCP first, falls back to default (SunEC) private static final String ECDH_PROVIDER_NAME = initEcdhProvider(); - private static final ThreadLocal THREAD_LOCAL_KEY_AGREEMENT = ThreadLocal.withInitial(() -> { - try { - return createKeyAgreement(); - } catch (NoSuchAlgorithmException | NoSuchProviderException e) { - throw new RuntimeException("Failed to create KeyAgreement", e); - } - }); private static String initEcdhProvider() { // Try ACCP (Amazon Corretto Crypto Provider) first @@ -42,14 +35,14 @@ private static String initEcdhProvider() { return null; } - private static KeyAgreement createKeyAgreement() throws NoSuchAlgorithmException, NoSuchProviderException { + public static KeyAgreement createKeyAgreement() throws NoSuchAlgorithmException { if (ECDH_PROVIDER_NAME != null) { - return KeyAgreement.getInstance("ECDH", ECDH_PROVIDER_NAME); + try { + return KeyAgreement.getInstance("ECDH", ECDH_PROVIDER_NAME); + } catch (NoSuchProviderException e) { + LOGGER.info("{} is not available: {}", ECDH_PROVIDER_NAME, e.getMessage()); + } } return KeyAgreement.getInstance("ECDH"); } - - public static KeyAgreement getKeyAgreement() { - return THREAD_LOCAL_KEY_AGREEMENT.get(); - } } diff --git a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java index ce36faf8d..4f45dfbed 100644 --- a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java +++ b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java @@ -409,7 +409,7 @@ private void handleClientSideTokenGenerateImpl(RoutingContext rc) throws NoSuchA } // Perform key agreement (uses cached provider: ACCP > SunEC) - final KeyAgreement ka = CryptoProviderService.getKeyAgreement(); + final KeyAgreement ka = CryptoProviderService.createKeyAgreement(); ka.init(clientSideKeypair.getPrivateKey()); ka.doPhase(clientPublicKey, true); diff --git a/src/test/java/com/uid2/operator/ClientSideTokenGenerateTestUtil.java b/src/test/java/com/uid2/operator/ClientSideTokenGenerateTestUtil.java index 22029a0ff..22219ae23 100644 --- a/src/test/java/com/uid2/operator/ClientSideTokenGenerateTestUtil.java +++ b/src/test/java/com/uid2/operator/ClientSideTokenGenerateTestUtil.java @@ -1,5 +1,7 @@ package com.uid2.operator; +import com.uid2.operator.service.CryptoProviderService; + import javax.crypto.*; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; @@ -37,7 +39,7 @@ public static PrivateKey stringToPrivateKey(String privateKeyString, KeyFactory } public static SecretKey deriveKey(PublicKey serverPublicKey, PrivateKey clientPrivateKey) throws NoSuchAlgorithmException, InvalidKeyException { - KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH"); + KeyAgreement keyAgreement = CryptoProviderService.createKeyAgreement(); keyAgreement.init(clientPrivateKey); keyAgreement.doPhase(serverPublicKey, true);