Skip to content

MOSIP-36428: ecc algorithms encryption support#525

Open
nagendra0721 wants to merge 12 commits intomosip:developfrom
nagendra0721:dev-eccSupport
Open

MOSIP-36428: ecc algorithms encryption support#525
nagendra0721 wants to merge 12 commits intomosip:developfrom
nagendra0721:dev-eccSupport

Conversation

@nagendra0721
Copy link
Contributor

@nagendra0721 nagendra0721 commented Feb 25, 2026

Summary by CodeRabbit

  • New Features

    • Added EC (secp256r1/secp256k1), X25519 and Ed25519 support across key generation, encryption/decryption, JWE/JWT and signing flows.
    • New endpoints for RSA signature key generation and certificate retrieval (v2).
    • Added Keys Algorithm Migrator service (packaging and startup).
  • API

    • Public EC asymmetric crypto service and ECC-aware utilities for curve/algorithm resolution and key handling.
  • Errors

    • New error codes for unsupported EC curves, JWE encryption, X25519 CSR and RSA sign reference cases.
  • Tests

    • Expanded tests for EC/X25519/Ed25519 flows and migration scenarios.

Signed-off-by: nagendra0721 <nagendra0718@gmail.com>
Signed-off-by: nagendra0721 <nagendra0718@gmail.com>
Signed-off-by: nagendra0721 <nagendra0718@gmail.com>
Signed-off-by: nagendra0721 <nagendra0718@gmail.com>
Signed-off-by: nagendra0721 <nagendra0718@gmail.com>
@coderabbitai
Copy link

coderabbitai bot commented Feb 25, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds ECC (secp256r1/secp256k1) and X25519 support across the keymanager: new EcCryptomanagerService + impl, ECC-aware encrypt/decrypt and JWE/JWT branching, key generation/keystore updates for EC/X25519/Ed25519, new constants/error codes, controller/service API additions, tests, and a Keys Algorithm Migrator module.

Changes

Cohort / File(s) Summary
ECC Core & Service
kernel/.../cryptomanager/service/EcCryptomanagerService.java, kernel/.../cryptomanager/service/impl/EcCryptomanagerServiceImpl.java
New EC/X25519 asymmetric interface and implementation: ephemeral key exchange (ECDH/XDH), HKDF-SHA256, AES‑GCM encrypt/decrypt, IV/AAD handling, ephemeral-key helpers and key-agreement utilities.
Cryptomanager Integration
kernel/.../cryptomanager/service/impl/CryptomanagerServiceImpl.java, kernel/.../cryptomanager/util/CryptomanagerUtils.java, kernel/.../cryptomanager/constant/CryptomanagerConstant.java, kernel/.../cryptomanager/constant/CryptomanagerErrorCode.java
Encrypt/decrypt and JWE/JWT flows now branch RSA vs ECC; added ecCurveName config, EcCryptomanagerService wiring, header/algorithm extraction, EC headers/constants and new error codes for unsupported curves/JWE.
Key Generation Utilities
kernel/.../keygenerator/bouncycastle/KeyGenerator.java, kernel/.../keygenerator/bouncycastle/util/KeyGeneratorUtils.java
Added EC and X25519 key-pair generation helpers and KeyPairGenerator factory methods; small RSA key-generation change to use centralized constant.
Keystore / HSM Wiring
kernel/.../keymanager/hsm/.../KeyStoreImpl.java, .../PKCS11KeyStoreImpl.java, .../PKCS12KeyStoreImpl.java, .../CertificateUtility.java, .../KeymanagerConstant.java, .../KeymanagerErrorConstant.java
Wired Ed25519/X25519 algorithms into keystore flows, unified RSA key-type constant usage, provider-aware certificate conversion, and added sign-algorithm constants and new keystore error codes.
Keymanager Service & Controller
kernel/.../keymanagerservice/service/impl/KeymanagerServiceImpl.java, .../KeymanagerService.java, .../controller/KeymanagerController.java
New APIs generateRSASignKey/getCertificateV2; extended generate/store flows to support RSA/ECC/Ed25519/X25519, added ecCurveName config, and controller endpoints with security/Swagger annotations.
Utilities & Migration
kernel/.../keymanagerservice/util/KeymanagerUtil.java, .../keymanagerservice/helper/PrivateKeyDecryptorHelper.java, .../SessionKeyDecrytorHelper.java, keys-migrator/.../BaseKeysMigrator.java, zkcryptoservice/.../ZKCryptoManagerServiceImpl.java
Replaced hardcoded RSA KeyFactory selection with algorithm derived from cert/public key; added ecCrypto usage for ECC encrypt/decrypt paths and exposed getEcCurveName helper.
Signature & Certificate Handling
kernel/.../signature/.../SignatureUtil.java, SignatureAlgorithmIdentifyEnum.java, SignatureProviderEnum.java, SignatureServiceImpl.java, CoseSignatureServiceImpl.java
Dynamic JWT signing algorithm selection from certificate key/curve OID, new signature/provider enum entries, logging additions, and ED25519 handling.
Tests
kernel/.../cryptomanager/test/..., keymanagerservice/test/..., zkcryptoservice/test/..., keymigrate/test/...
New EcCryptomanagerService tests (secp256k1, secp256r1, X25519) and multiple test updates/mocks/lenient stubbing to cover ECC flows and new APIs.
Keys Algorithm Migrator Module
keys-algorithm-migrator/... (pom.xml, MigrateKeysAlgorithmApplication.java, ComponentKeysAlgorithmMigrator.java, Dockerfile, configure_start.sh, *.properties, README.md)
New Maven module and Spring Boot app to orchestrate key-algorithm migration/rotation, with Docker packaging and PKCS#11 client install script.
Project & Config
kernel/pom.xml, kernel/.../application-local.properties, keys-algorithm-migrator/src/main/resources/*
Parent POM includes new module; properties added for ecc-curve-name, algorithm mapping, and expanded role/endpoint config entries; new bootstrap/local properties for migrator module.

Sequence Diagram

sequenceDiagram
    participant Client
    participant CryptoSvc as CryptomanagerService
    participant EC as EcCryptomanagerService
    participant HSM as KeyManager/HSM
    participant DB as Database

    Note over Client,HSM: EC Encryption Flow
    Client->>CryptoSvc: encrypt(data, recipientCert/publicKey)
    activate CryptoSvc
    CryptoSvc->>CryptoSvc: detect algorithm = ECC
    CryptoSvc->>EC: asymmetricEcEncrypt(publicKey, data, curveName)
    activate EC
    EC->>EC: generate ephemeral key pair
    EC->>EC: perform ECDH/XDH key agreement
    EC->>EC: HKDF-SHA256 derive AES key
    EC->>EC: AES-GCM encrypt with IV (+AAD)
    EC-->>CryptoSvc: encryptedPayload (ciphertext + iv + ephemeralPubKey)
    deactivate EC
    CryptoSvc->>HSM: retrieve certificate thumbprint/metadata
    CryptoSvc->>CryptoSvc: prepend header (algorithm, thumbprint)
    CryptoSvc-->>Client: return finalEncryptedPayload
    deactivate CryptoSvc

    Note over Client,DB: EC Decryption Flow
    Client->>CryptoSvc: decrypt(encryptedPayload)
    activate CryptoSvc
    CryptoSvc->>CryptoSvc: extract header -> algorithm = ECC, thumbprint
    CryptoSvc->>HSM: retrieve private key by thumbprint
    CryptoSvc->>EC: asymmetricEcDecrypt(privateKey, encryptedPayload, curveName)
    activate EC
    EC->>EC: extract ephemeralPubKey and IV
    EC->>EC: ECDH/XDH with privateKey and ephemeralPubKey
    EC->>EC: HKDF derive AES key
    EC->>EC: AES-GCM decrypt -> plaintext
    EC-->>CryptoSvc: plaintext
    deactivate EC
    CryptoSvc-->>Client: return plaintext
    deactivate CryptoSvc
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related issues

Poem

🐰 Hop, hop — new curves take flight,

Ephemeral keys shimmer in night,
X25519 leaps, secp twirls so bright,
I nibble bytes and guard each byte,
Secure carrots tucked in code delight.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.81% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main objective: adding ECC algorithms encryption support. It is specific, concise, and clearly reflects the core changes across multiple components.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Note

Due to the large number of review comments, Critical severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanager/hsm/util/CertificateUtility.java (1)

137-162: ⚠️ Potential issue | 🔴 Critical

SAN-path private overload still uses the passed-in signAlgorithm directly — ECC/Ed25519 certificate signing with SANs will use the wrong algorithm.

Line 143 still reads new JcaContentSignerBuilder(signAlgorithm). The non-SAN overload was correctly updated (line 119), but this overload was not. For EC or Ed25519 keys with Subject Alternative Names the caller-supplied signAlgorithm (often "SHA256withRSA" by default) will be used, causing an OperatorCreationException or a mis-signed certificate.

🐛 Proposed fix
-        ContentSigner certContentSigner = new JcaContentSignerBuilder(signAlgorithm).setProvider(providerName).build(signPrivateKey);
+        ContentSigner certContentSigner = new JcaContentSignerBuilder(getSignatureAlgorithm(signPrivateKey)).setProvider(providerName).build(signPrivateKey);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanager/hsm/util/CertificateUtility.java`
around lines 137 - 162, The generateX509Certificate overload is still
constructing the ContentSigner with the caller-supplied signAlgorithm (new
JcaContentSignerBuilder(signAlgorithm)), which breaks ECC/Ed25519 signing when
SANs are present; change it to choose the signing algorithm based on the signing
key type instead of blindly using signAlgorithm: inside generateX509Certificate
detect the signPrivateKey type (e.g., ECPrivateKey → use an ECDSA digest like
"SHA256withECDSA", EdDSA/Ed25519 → "Ed25519", RSA → fall back to the provided
signAlgorithm or an RSA default), then pass that resolved algorithm to
JcaContentSignerBuilder.setProvider(providerName). Ensure this mirrors the
approach used in the non-SAN overload so ECC/Ed25519 keys are signed with the
correct algorithm.
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keygenerator/bouncycastle/KeyGenerator.java (1)

47-48: ⚠️ Potential issue | 🟡 Minor

Remove unused asymmetricKeyAlgorithm field and its @Value injection.

The field at line 48 is injected but never used in this class. The getAsymmetricKey() method hardcodes KeymanagerConstant.RSA instead, making the configuration property dead code. Remove the field declaration and @Value annotation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keygenerator/bouncycastle/KeyGenerator.java`
around lines 47 - 48, Remove the unused injected field asymmetricKeyAlgorithm
and its `@Value` annotation from the KeyGenerator class: locate the field
declaration "private String asymmetricKeyAlgorithm" annotated with `@Value` and
delete it, since getAsymmetricKey() currently uses KeymanagerConstant.RSA
directly; ensure no other references to asymmetricKeyAlgorithm remain (search
for the symbol) and run a quick compile to confirm no missing usages.
🟠 Major comments (22)
kernel/keys-algorithm-migrator/src/main/resources/application-local.properties-4-4 (1)

4-4: ⚠️ Potential issue | 🟠 Major

Avoid committing HSM credentials in plaintext config

Line 4 hardcodes a sensitive value (keystore-pass=pin). Even in local profiles, this normalizes insecure secret handling and risks accidental reuse in non-local environments. Move this to environment/config-server secret injection.

Suggested change
-mosip.kernel.keymanager.hsm.keystore-pass=pin
+mosip.kernel.keymanager.hsm.keystore-pass=${MOSIP_HSM_KEYSTORE_PASS}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/keys-algorithm-migrator/src/main/resources/application-local.properties`
at line 4, The property mosip.kernel.keymanager.hsm.keystore-pass must not be
hardcoded; remove the literal "pin" and replace it with a secret reference (e.g.
an environment/config-server placeholder) so the keystore password is injected
at runtime rather than stored in source. Update any code or configuration that
reads mosip.kernel.keymanager.hsm.keystore-pass to accept the injected secret
(environment variable or config-server secret) and ensure local runs use a
developer-only secret store or .env excluded from VCS. Ensure no plaintext value
remains for mosip.kernel.keymanager.hsm.keystore-pass in the repo.
kernel/keys-algorithm-migrator/src/main/resources/bootstrap.properties-16-17 (1)

16-17: ⚠️ Potential issue | 🟠 Major

Reduce management endpoint exposure and health detail leakage

Lines 16–17 expose dangerous operational endpoints (refresh, restart) and detailed health information with no authorization requirement. Spring Boot Actuator documentation explicitly warns that restart is disabled by default and should only be enabled with strong authentication and network isolation. Exposing refresh requires equivalent controls.

  • Remove refresh and restart from management.endpoints.web.exposure.include (expose only info and health)
  • Change management.endpoint.health.show-details to when-authorized to prevent unauthenticated leakage of health component details
Suggested fix
- management.endpoint.health.show-details=always
- management.endpoints.web.exposure.include=info,health,refresh,restart
+ management.endpoint.health.show-details=when-authorized
+ management.endpoints.web.exposure.include=info,health
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kernel/keys-algorithm-migrator/src/main/resources/bootstrap.properties`
around lines 16 - 17, Update the Actuator configuration to avoid exposing
sensitive endpoints and leaking health details: set
management.endpoint.health.show-details to when-authorized (instead of always)
and remove refresh and restart from management.endpoints.web.exposure.include so
it only lists info and health; modify the properties named
management.endpoint.health.show-details and
management.endpoints.web.exposure.include accordingly and ensure any required
endpoint access is protected via authentication/authorization.
kernel/keys-algorithm-migrator/src/main/resources/bootstrap.properties-7-7 (1)

7-7: ⚠️ Potential issue | 🟠 Major

Externalize active profile instead of hardcoding local in committed config

Line 7 pins the application to local profile, creating deployment risk. If this jar runs in shared/dev/prod environments without proper CLI or environment variable overrides, it will always activate the local profile. Follow Spring Boot best practices: remove the hardcoded setting and set spring.profiles.active at deploy time via command-line args (e.g., --spring.profiles.active=prod) or environment variables (higher precedence than config files).

Suggested change
- spring.profiles.active=local
+ # Keep profile externalized (env/command-line), e.g. SPRING_PROFILES_ACTIVE
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kernel/keys-algorithm-migrator/src/main/resources/bootstrap.properties` at
line 7, Remove the hardcoded profile by deleting or neutralizing the
spring.profiles.active=local entry in bootstrap.properties so the app no longer
forces the "local" profile at runtime; rely on external overrides instead (use
--spring.profiles.active=<env> or the SPRING_PROFILES_ACTIVE env var at deploy
time) and update any deployment docs or scripts that previously depended on that
embedded setting.
kernel/keys-algorithm-migrator/configure_start.sh-7-7 (1)

7-7: ⚠️ Potential issue | 🟠 Major

ZIP path override is wired to a different env var name.

On Line 7, the script reads zip_file_path, but this PR’s Dockerfile sets hsm_zip_file_path. That makes runtime override brittle and can silently fall back to default path.

Proposed fix
- [ -z "$zip_file_path" ] && zip_path="$DEFAULT_ZIP_PATH" || zip_path="$zip_file_path"
+ zip_path="${zip_file_path:-${hsm_zip_file_path:-$DEFAULT_ZIP_PATH}}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kernel/keys-algorithm-migrator/configure_start.sh` at line 7, The env var
check in configure_start.sh uses zip_file_path but the Dockerfile sets
hsm_zip_file_path, causing overrides to be ignored; update the conditional that
assigns zip_path (currently referencing zip_file_path) to instead check
hsm_zip_file_path (falling back to DEFAULT_ZIP_PATH if empty) so runtime
overrides work correctly, and keep the zip_path variable name unchanged.
kernel/keys-algorithm-migrator/configure_start.sh-18-24 (1)

18-24: ⚠️ Potential issue | 🟠 Major

Downloaded installer is executed without integrity verification.

The script runs install.sh from a freshly downloaded ZIP without verifying artifact integrity. That creates a direct supply-chain execution risk.

Proposed fix
 wget "$artifactory_url_env/$zip_path"
 echo "Downloaded $artifactory_url_env/$zip_path"
 
-unzip $FILE_NAME
+if [ -n "${hsm_zip_sha256:-}" ]; then
+  echo "${hsm_zip_sha256}  ${FILE_NAME}" | sha256sum -c -
+fi
+
+unzip "$FILE_NAME"
 echo "Attempting to install"
 cd ./$DIR_NAME && ./install.sh
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kernel/keys-algorithm-migrator/configure_start.sh` around lines 18 - 24, The
script currently downloads and immediately unzips/runs the installer (wget ->
unzip -> cd $DIR_NAME && ./install.sh) without integrity checks; update the
logic to fetch and verify the artifact before execution by downloading a
checksum or signature alongside the ZIP (e.g. $zip_path.sha256 or
$zip_path.asc), verify the downloaded FILE_NAME using sha256sum --check or gpg
--verify, abort and log an error via non-zero exit if verification fails, only
then unzip and run the installer in $DIR_NAME; reference FILE_NAME, DIR_NAME and
install.sh when implementing the verification step and ensure failures prevent
execution.
kernel/keys-algorithm-migrator/Dockerfile-96-96 (1)

96-96: ⚠️ Potential issue | 🟠 Major

Exec-form CMD passes literal ${...} placeholders instead of expanding environment variables.

Line 96 uses JSON-array CMD form, which does not invoke a shell. Environment variables like ${loader_path_env} are passed literally to the Java process instead of being expanded, breaking runtime configuration.

Wrap the command with sh -c to enable shell variable expansion:

Proposed fix
-CMD ["java","-jar", "-Dloader.path=${loader_path_env}", "-Dspring.cloud.config.label=${spring_config_label_env}","-Dspring.cloud.config.name=${spring_config_name_env}", "-Dspring.profiles.active=${active_profile_env}", "-Dspring.cloud.config.uri=${spring_config_url_env}", "./keys-algorithm-migrator.jar"]
+CMD ["sh","-c","exec java -jar \
+  -Dloader.path=\"$loader_path_env\" \
+  -Dspring.cloud.config.label=\"$spring_config_label_env\" \
+  -Dspring.cloud.config.name=\"$spring_config_name_env\" \
+  -Dspring.profiles.active=\"$active_profile_env\" \
+  -Dspring.cloud.config.uri=\"$spring_config_url_env\" \
+  ./keys-algorithm-migrator.jar"]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kernel/keys-algorithm-migrator/Dockerfile` at line 96, The CMD currently uses
the exec/JSON form so placeholders like ${loader_path_env},
${spring_config_label_env}, ${spring_config_name_env}, ${active_profile_env},
and ${spring_config_url_env} are passed literally to the JVM; change the
Dockerfile CMD invocation for keys-algorithm-migrator.jar to run via a shell so
environment variables are expanded (e.g., wrap the entire command with sh -c
"<java ... ./keys-algorithm-migrator.jar>"), ensuring the same JVM options and
-D properties are preserved and referenced by their existing names.
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/signature/util/SignatureUtil.java-612-616 (1)

612-616: ⚠️ Potential issue | 🟠 Major

Potential ClassCastException if EC key uses explicit parameters instead of a named curve.

Line 614 casts subjectPublicKeyInfo.getAlgorithm().getParameters() directly to ASN1ObjectIdentifier. If the EC key encodes explicit curve parameters (not a named curve OID), .getParameters() will return an ASN1Sequence, causing a ClassCastException at runtime.

Consider adding a type check or catching the cast failure.

🛡️ Proposed defensive fix
         if (KeymanagerConstant.EC_KEY_TYPE.equalsIgnoreCase(algorithm)) {
             SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(publicKey.getEncoded());
-            ASN1ObjectIdentifier curveOid = (ASN1ObjectIdentifier) subjectPublicKeyInfo.getAlgorithm().getParameters();
-
-            return mapCurveOidToCurveName(curveOid.getId());
+            Object params = subjectPublicKeyInfo.getAlgorithm().getParameters();
+            if (!(params instanceof ASN1ObjectIdentifier)) {
+                throw new io.mosip.kernel.core.exception.NoSuchAlgorithmException(
+                        KeymanagerErrorConstant.NOT_SUPPORTED_CURVE_VALUE.getErrorCode(),
+                        KeymanagerErrorConstant.NOT_SUPPORTED_CURVE_VALUE.getErrorMessage());
+            }
+            return mapCurveOidToCurveName(((ASN1ObjectIdentifier) params).getId());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/signature/util/SignatureUtil.java`
around lines 612 - 616, The code in SignatureUtil that handles EC public keys
casts subjectPublicKeyInfo.getAlgorithm().getParameters() to
ASN1ObjectIdentifier directly (used in the EC branch before calling
mapCurveOidToCurveName), which can throw ClassCastException for keys with
explicit EC parameters; modify the EC key handling in the method to first check
the parameter object's type (e.g., instanceof ASN1ObjectIdentifier vs
ASN1Sequence), and if it's an ASN1ObjectIdentifier extract the OID and call
mapCurveOidToCurveName(curveOid.getId()), otherwise handle the
explicit-parameters case by either parsing the ASN1Sequence to derive the curve
name or throw a clear, descriptive exception/log (including the raw parameters)
so callers can handle unsupported explicit-parameter keys.
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymigrate/service/impl/KeyMigratorServiceImpl.java-401-416 (1)

401-416: ⚠️ Potential issue | 🟠 Major

ECB mode remains a cryptographic risk in both RSA and EC branches.

Line [401] and Line [414] use ECB-mode transformation, which lacks semantic security and integrity protection for repeated/structured inputs. For key wrapping/migration, move to an authenticated scheme (e.g., AES-GCM with IV/tag management, or a standard key-wrap construction).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymigrate/service/impl/KeyMigratorServiceImpl.java`
around lines 401 - 416, The code is using aesECBTransformation with
Cipher.getInstance(...) and cipher.init(...)/cipher.doFinal(...) (seen around
aesECBTransformation, zkMasterKey, Cipher.getInstance, cipher.init,
cipher.doFinal in both the RSA and EC branches where
ecCrypto.asymmetricEcDecrypt is used) which is insecure; replace ECB-based
encryption with an authenticated key-wrap or AEAD mode (e.g., AES-GCM or
RFC3394/AES Key Wrap): update the aesECBTransformation constant to an
AEAD/key-wrap transformation, instantiate Cipher accordingly, generate and use a
secure IV/nonce (or the key-wrap API) when encrypting the secretDataBytes,
include the resulting IV/nonce and authentication tag (or wrapped output)
alongside the ciphertext for storage/transfer, and update the corresponding
decryption logic to extract IV/tag and perform authenticated verification before
returning the plaintext; apply this change in both branches where
Cipher.getInstance(...) / cipher.init(...)/cipher.doFinal(...) are called and
ensure zkMasterKey usage matches the chosen AEAD/key-wrap API.
kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/keymanagerservice/test/controller/KeymanagerControllerTest.java-306-314 (1)

306-314: ⚠️ Potential issue | 🟠 Major

Do not swallow all exceptions in testGenerateSymmetricKeyForce.

Line [310] catches Exception and then only checks non-null, so the test passes even on unexpected failures.

✅ Narrow the catch to expected infra failures only
-        try {
-            SymmetricKeyGenerateResponseDto response = keymanagerService.generateSymmetricKey(requestDto);
-            Assert.assertNotNull(response);
-            Assert.assertEquals("Generation Success", response.getStatus());
-        } catch (Exception e) {
-            // If KeystoreProcessing exception occurs, it might be due to HSM/keystore not being available in test
-            // In that case, we should still verify the method can be called
-            Assert.assertNotNull(e);
-        }
+        try {
+            SymmetricKeyGenerateResponseDto response = keymanagerService.generateSymmetricKey(requestDto);
+            Assert.assertNotNull(response);
+            Assert.assertEquals("Generation Success", response.getStatus());
+        } catch (io.mosip.kernel.core.keymanager.exception.KeystoreProcessingException e) {
+            org.junit.Assume.assumeNoException("Keystore unavailable in this test environment", e);
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/keymanagerservice/test/controller/KeymanagerControllerTest.java`
around lines 306 - 314, In testGenerateSymmetricKeyForce inside
KeymanagerControllerTest, don't catch java.lang.Exception broadly; instead catch
only the expected infra-specific exceptions (e.g., KeystoreProcessingException
or the HSM/keystore unavailability exception your code throws) around the call
to keymanagerService.generateSymmetricKey(requestDto), assert details on that
specific exception if caught, and let any other unexpected exceptions propagate
(remove the generic catch or rethrow them) so test failures surface real bugs.
kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/keymanagerservice/test/service/KeymanagerServiceImplTest.java-424-439 (1)

424-439: ⚠️ Potential issue | 🟠 Major

Avoid broad exception swallowing in testGenerateSymmetricKey.

Line [435] makes the test pass on any exception, which can hide real defects.

✅ Suggested tightening
-        try {
+        try {
             SymmetricKeyGenerateResponseDto result = service.generateSymmetricKey(requestDto);
             Assert.assertEquals("Generation Success", result.getStatus());
@@
             requestDto.setForce(false);
             SymmetricKeyGenerateResponseDto result2 = service.generateSymmetricKey(requestDto);
             Assert.assertEquals("Key Exists.", result2.getStatus());
-        } catch (Exception e) {
-            // If KeystoreProcessing exception occurs, it might be due to HSM/keystore not being available in test
-            // In that case, we should still verify the method can be called
-            Assert.assertNotNull(e);
+        } catch (io.mosip.kernel.core.keymanager.exception.KeystoreProcessingException e) {
+            org.junit.Assume.assumeNoException("Keystore unavailable in this test environment", e);
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/keymanagerservice/test/service/KeymanagerServiceImplTest.java`
around lines 424 - 439, The test testGenerateSymmetricKey currently swallows all
Exceptions around calls to service.generateSymmetricKey; narrow the handling so
real failures surface: remove the broad catch and let the test method declare
throws Exception (or alternatively catch only the specific expected exception
type such as KeystoreProcessingException) and in that specific catch assert the
known expected behavior, but for any other exception rethrow or call
Assert.fail(...) so unexpected exceptions fail the test; update references in
KeymanagerServiceImplTest to replace the generic catch(Exception e) with the
specific handling around service.generateSymmetricKey.
kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/keymanagerservice/test/service/KeymanagerServiceImplTest.java-694-714 (1)

694-714: ⚠️ Potential issue | 🟠 Major

testGenerateKeyPairInHSM currently passes even on unexpected failures.

Line [710] catches all exceptions, so this test can silently succeed during functional breakage.

✅ Suggested tightening
-        } catch (Exception e) {
-            // If KeystoreProcessing exception occurs, it might be due to HSM/keystore not being available in test
-            // In that case, we should still verify the method can be called
-            Assert.assertNotNull(e);
+        } catch (io.mosip.kernel.core.keymanager.exception.KeystoreProcessingException e) {
+            org.junit.Assume.assumeNoException("Keystore unavailable in this test environment", e);
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/keymanagerservice/test/service/KeymanagerServiceImplTest.java`
around lines 694 - 714, The test testGenerateKeyPairInHSM currently swallows all
exceptions in a broad catch(Exception) which hides real failures; remove the
generic try/catch (or replace it with a catch only for the expected
KeystoreProcessingException), let unexpected exceptions propagate so the test
fails, and if you must catch expected HSM/keystore errors, catch
KeystoreProcessingException explicitly and assert its type/message; update the
block around calls to service.generateMasterKey, service.getCertificate,
service.generateECSignKey and updateKeyExpiry accordingly so only expected
HSM-related exceptions are handled and all other exceptions are rethrown or
allowed to fail the test.
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanager/hsm/util/CertificateUtility.java-127-130 (1)

127-130: ⚠️ Potential issue | 🟠 Major

Potential NullPointerExceptionproviderName is not null-checked before .equals("BC").

If providerName is null (e.g., not configured), calling .equals("BC") on it throws an NPE. Invert the comparison to use the string literal as the receiver.

🛡️ Proposed fix (apply to both occurrences)
-            if (providerName.equals("BC"))
+            if ("BC".equals(providerName))

Also applies to: 154-157

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanager/hsm/util/CertificateUtility.java`
around lines 127 - 130, providerName is compared with "BC" using
providerName.equals("BC") which can NPE if providerName is null; in
CertificateUtility update both occurrences where JcaX509CertificateConverter is
constructed (the branches returning new
JcaX509CertificateConverter().setProvider(providerName).getCertificate(certHolder)
vs new JcaX509CertificateConverter().getCertificate(certHolder)) to either
invert the equals check to "BC".equals(providerName) or perform an explicit
null-check on providerName before calling equals, so the logic safely selects
setProvider(providerName) only when providerName is non-null and equals "BC".
kernel/keys-algorithm-migrator/src/main/java/io/mosip/kernel/migratealgorithm/MigrateKeysAlgorithmApplication.java-14-16 (2)

14-16: ⚠️ Potential issue | 🟠 Major

scanBasePackages with trailing .* is not a supported glob pattern — required beans may not be discovered.

scanBasePackages allows wildcard string filtering, however the standard and well-documented form uses a plain package name such as "io.mosip.kernel.keygenerator", which automatically scans the configuration class package and all its sub-packages. Appending .* is an unusual pattern; the official API describes scanBasePackages simply as "Base packages to scan for annotated components", with scanBasePackageClasses() as a type-safe alternative — there is no documented glob expansion in scanBasePackages itself. Passing "io.mosip.kernel.keygenerator.*" would look for a package literally named with that suffix, which doesn't exist, causing beans in io.mosip.kernel.keygenerator.bouncycastle and sibling packages to be silently skipped and the migrator to fail at startup due to missing dependencies.

Remove the trailing .* from every entry:

🐛 Proposed fix
-@SpringBootApplication(scanBasePackages = { "io.mosip.kernel.keygenerator.*", "io.mosip.kernel.keymanagerservice.*",
-        "io.mosip.kernel.keymanager.*", "io.mosip.kernel.crypto.*", "io.mosip.kernel.cryptomanager.*",
-        "io.mosip.kernel.migratealgorithm.*" })
+@SpringBootApplication(scanBasePackages = { "io.mosip.kernel.keygenerator", "io.mosip.kernel.keymanagerservice",
+        "io.mosip.kernel.keymanager", "io.mosip.kernel.crypto", "io.mosip.kernel.cryptomanager",
+        "io.mosip.kernel.migratealgorithm" })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/keys-algorithm-migrator/src/main/java/io/mosip/kernel/migratealgorithm/MigrateKeysAlgorithmApplication.java`
around lines 14 - 16, The scanBasePackages entries in the `@SpringBootApplication`
on MigrateKeysAlgorithmApplication are using invalid trailing ".*" patterns
which prevents component scanning from finding beans; remove the ".*" suffix
from each package string (e.g., change "io.mosip.kernel.keygenerator.*" to
"io.mosip.kernel.keygenerator") so Spring scans those base packages and their
subpackages correctly; update all entries in the scanBasePackages array
accordingly (or consider using scanBasePackageClasses for type-safe scanning).

14-16: ⚠️ Potential issue | 🟠 Major

scanBasePackages uses invalid pattern syntax — correct to standard package names.

The scanBasePackages attribute accepts either plain package names or Ant-style patterns (e.g., "io.mosip.kernel.**"). The current syntax "io.mosip.kernel.keygenerator.*" (single dot and asterisk) is not recognized as a valid pattern. Since Spring automatically recurses into sub-packages when given a plain package name, removing the .* suffix is the simplest fix.

🐛 Proposed fix
-@SpringBootApplication(scanBasePackages = { "io.mosip.kernel.keygenerator.*", "io.mosip.kernel.keymanagerservice.*",
-        "io.mosip.kernel.keymanager.*", "io.mosip.kernel.crypto.*", "io.mosip.kernel.cryptomanager.*",
-        "io.mosip.kernel.migratealgorithm.*" })
+@SpringBootApplication(scanBasePackages = { "io.mosip.kernel.keygenerator", "io.mosip.kernel.keymanagerservice",
+        "io.mosip.kernel.keymanager", "io.mosip.kernel.crypto", "io.mosip.kernel.cryptomanager",
+        "io.mosip.kernel.migratealgorithm" })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/keys-algorithm-migrator/src/main/java/io/mosip/kernel/migratealgorithm/MigrateKeysAlgorithmApplication.java`
around lines 14 - 16, The scanBasePackages value in the `@SpringBootApplication`
annotation on MigrateKeysAlgorithmApplication uses invalid pattern syntax like
"io.mosip.kernel.keygenerator.*"; update the scanBasePackages attribute to use
plain package names (e.g., "io.mosip.kernel.keygenerator",
"io.mosip.kernel.keymanagerservice", "io.mosip.kernel.keymanager",
"io.mosip.kernel.crypto", "io.mosip.kernel.cryptomanager",
"io.mosip.kernel.migratealgorithm") so Spring can properly scan subpackages;
locate the annotation on the MigrateKeysAlgorithmApplication class and replace
each "package.*" entry with the corresponding plain package name.
kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/zkcryptoservice/test/ZKCryptoManagerServiceTest.java-366-377 (1)

366-377: ⚠️ Potential issue | 🟠 Major

Tests should not accept NullPointerException as a valid outcome.

Line 372–Line 377 and Line 407–Line 412 currently allow NPE as a “pass” condition. This hides regressions and normalizes undefined behavior.

✅ Suggested fix
-        } catch (ZKCryptoException e) {
-            // Expected - no matching thumbprint found, encRandomKey will be null
-            assertNotNull(e);
-        } catch (NullPointerException e) {
-            // NPE can occur if Objects.requireNonNull(kyAlias) is called with null
-            // This happens because the code accesses kyAlias before checking if encRandomKey is null
-            // This is acceptable as it indicates the expected failure path
-            assertNotNull(e);
-        }
+        } catch (ZKCryptoException e) {
+            assertNotNull(e);
+        }
@@
-        } catch (ZKCryptoException e) {
-            // Expected - empty keyAliases list, no match found, encRandomKey will be null
-            assertNotNull(e);
-        } catch (NullPointerException e) {
-            // NPE can occur if Objects.requireNonNull(kyAlias) is called with null
-            // This happens because the code accesses kyAlias before checking if encRandomKey is null
-            // This is acceptable as it indicates the expected failure path
-            assertNotNull(e);
-        }
+        } catch (ZKCryptoException e) {
+            assertNotNull(e);
+        }

Also applies to: 401-412

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/zkcryptoservice/test/ZKCryptoManagerServiceTest.java`
around lines 366 - 377, The test currently treats NullPointerException as an
acceptable outcome; remove the catch for NullPointerException in
ZKCryptoManagerServiceTest so NPEs no longer pass silently—either let NPE bubble
(failing the test) or replace the NullPointerException catch with a fail() that
reports an unexpected NPE; keep the existing expectation that
zkReEncryptRandomKey(encryptedKey) should throw ZKCryptoException and only
catch/assert that exception.
kernel/keys-algorithm-migrator/src/main/java/io/mosip/kernel/migratealgorithm/impl/ComponentKeysAlgorithmMigrator.java-119-124 (1)

119-124: ⚠️ Potential issue | 🟠 Major

Guard against null keyAliasList before invalidation.

Line 121 assumes keyAliasList is non-null; if repository lookup returns no CURRENTKEYALIAS, migration fails with NPE and stops processing.

✅ Suggested fix
     private void invalidateKeyAlias(String appId, String refId, List<KeyAlias> keyAliasList, LocalDateTime timestamp) {
+        if (keyAliasList == null || keyAliasList.isEmpty()) {
+            LOGGER.info("No current key aliases to invalidate for AppId: " + appId + ", RefId: " + refId);
+            return;
+        }
         LocalDateTime expireTime = timestamp.minusMinutes(1L);
         keyAliasList.forEach(alias -> {
             dbHelper.storeKeyInAlias(appId, alias.getKeyGenerationTime(), refId, alias.getAlias(),
                     expireTime, alias.getCertThumbprint(), alias.getUniqueIdentifier());
         });
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/keys-algorithm-migrator/src/main/java/io/mosip/kernel/migratealgorithm/impl/ComponentKeysAlgorithmMigrator.java`
around lines 119 - 124, The method invalidateKeyAlias currently assumes
keyAliasList is non-null and will NPE if the repository returns no
CURRENTKEYALIAS; update invalidateKeyAlias to guard against null/empty lists by
returning early when keyAliasList == null || keyAliasList.isEmpty(), so the
dbHelper.storeKeyInAlias loop is only executed when there are entries to
invalidate; keep the existing expireTime computation and forEach logic unchanged
otherwise.
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/util/KeymanagerUtil.java-618-622 (1)

618-622: ⚠️ Potential issue | 🟠 Major

X25519 cannot be used for PKCS#10 CSR signing—remove it from signing algorithm paths.

Lines 618-622 and 641-643 incorrectly route X25519 (a key-agreement algorithm) to Ed25519 signing logic. Per RFC 8410, X25519 is limited to key agreement and cannot sign. The generateCSR() method has a defensive check that blocks X25519, but the buildResponseObject() CSR path (line 820-826 in KeymanagerServiceImpl) calls getCSR() without validation, leaving a vulnerable code path.

💡 Suggested fix

Add X25519 validation in buildResponseObject() CSR path before calling getCSR():

if (responseObjectType.toUpperCase().equals(KeymanagerConstant.REQUEST_TYPE_CSR)) {
    LOGGER.info(KeymanagerConstant.SESSIONID, KeymanagerConstant.APPLICATIONID, appId,
        "Getting Key CSR for application ID: " + appId + ", RefId: " + refId);
    
    Optional<io.mosip.kernel.keymanagerservice.entity.KeyStore> keyFromDBStore = dbHelper.getKeyStoreFromDB(keyAlias);
    Object[] keyDetailsArr = getKeyDetails(keyFromDBStore, keyAlias);
    if (Objects.isNull(x509Cert)){
        x509Cert = (X509Certificate) keyDetailsArr[1];
    }
+   
+   if (x509Cert.getPublicKey().getAlgorithm().equals(KeymanagerConstant.X25519_KEY_TYPE)) {
+       throw new KeymanagerServiceException(KeymanagerErrorConstant.X25519_KEY_CSR_NOT_SUPPORTED.getErrorCode(),
+               KeymanagerErrorConstant.X25519_KEY_CSR_NOT_SUPPORTED.getErrorMessage());
+   }
+   
    PublicKey publicKey = x509Cert.getPublicKey();
    PrivateKey privateKey =  (PrivateKey) keyDetailsArr[0];
    KeyPairGenerateResponseDto responseDto = new KeyPairGenerateResponseDto();

Additionally, remove X25519 from the signing algorithm selection in KeymanagerUtil:

// In getCSR() method (lines 618-622):
-            if (privateKeyAlgo.equals(KeymanagerConstant.ED25519_KEY_TYPE) || 
-                privateKeyAlgo.equals(KeymanagerConstant.X25519_KEY_TYPE) ||
-                keyAlgorithm.equals(KeymanagerConstant.X25519_KEY_TYPE)) {
+            if (privateKeyAlgo.equals(KeymanagerConstant.ED25519_KEY_TYPE)) {
                 contentSigner = new JcaContentSignerBuilder(edSignAlgorithm).build(privateKey);

// In getSignatureAlgorithm() method (lines 641-643):
-        else if (keyAlgorithm.equals(KeymanagerConstant.ED25519_KEY_TYPE) || 
-                 keyAlgorithm.equals(KeymanagerConstant.ED25519_ALG_OID) || 
-                 keyAlgorithm.equals(KeymanagerConstant.EDDSA_KEY_TYPE) ||
-                 keyAlgorithm.equals(KeymanagerConstant.X25519_KEY_TYPE)) 
+        else if (keyAlgorithm.equals(KeymanagerConstant.ED25519_KEY_TYPE) || 
+                 keyAlgorithm.equals(KeymanagerConstant.ED25519_ALG_OID) || 
+                 keyAlgorithm.equals(KeymanagerConstant.EDDSA_KEY_TYPE)) 
             return edSignAlgorithm;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/util/KeymanagerUtil.java`
around lines 618 - 622, Remove X25519 from the signing-path in KeymanagerUtil by
ensuring the condition that picks the Ed25519 signer (the block that checks
privateKey.getAlgorithm()/privateKeyAlgo and uses
JcaContentSignerBuilder(edSignAlgorithm)) does not treat
KeymanagerConstant.X25519_KEY_TYPE as a signing key; only Ed25519 should map to
edSignAlgorithm. Also add an explicit validation in the CSR-building path in
KeymanagerServiceImpl (the method buildResponseObject()) before calling
getCSR(): check the keyAlgorithm/privateKeyAlgo against
KeymanagerConstant.X25519_KEY_TYPE and throw or return an error (same behavior
as generateCSR()) if X25519 is detected so getCSR() is never invoked for X25519
keys. Ensure references to getCSR(), generateCSR(), KeymanagerUtil, and
KeymanagerConstant.X25519_KEY_TYPE are used to locate the changes.
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/signature/service/impl/SignatureServiceImpl.java-677-679 (1)

677-679: ⚠️ Potential issue | 🟠 Major

Do not use PrivateKey.getAlgorithm() as the JOSE signature algorithm.

At Line 677 and Line 740, fallback uses key algorithm names (RSA / EC / Ed25519), but SignatureProviderEnum resolves JOSE identifiers (PS256, ES256, ES256K, EdDSA). This can incorrectly fall back to PS256 for EC/Ed keys and fail signing.

💡 Proposed fix
-        String signAlgorithm = SignatureUtil.isDataValid(signatureReq.getSignAlgorithm())
-                ? signatureReq.getSignAlgorithm() : certificateResponse.getCertificateEntry().getPrivateKey().getAlgorithm();
+        String signAlgorithm = SignatureUtil.isDataValid(signatureReq.getSignAlgorithm())
+                ? signatureReq.getSignAlgorithm()
+                : SignatureUtil.getJwtSignAlgorithm(certificateResponse.getCertificateEntry().getChain()[0]);
@@
-        String signatureAlgorithm = SignatureUtil.isDataValid(signatureReq.getSignAlgorithm())
-                ? signatureReq.getSignAlgorithm()
-                : certificateResponse.getCertificateEntry().getPrivateKey().getAlgorithm();
+        String signatureAlgorithm = SignatureUtil.isDataValid(signatureReq.getSignAlgorithm())
+                ? signatureReq.getSignAlgorithm()
+                : SignatureUtil.getJwtSignAlgorithm(certificateResponse.getCertificateEntry().getChain()[0]);

Also applies to: 740-743

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/signature/service/impl/SignatureServiceImpl.java`
around lines 677 - 679, The code falls back to using PrivateKey.getAlgorithm()
(via certificateResponse.getCertificateEntry().getPrivateKey()) as the JOSE
signature algorithm when signatureReq.getSignAlgorithm() is absent, which mixes
key algorithm names (RSA/EC/Ed25519) with JOSE identifiers; update the fallback
in SignatureServiceImpl so that if signatureReq.getSignAlgorithm() is invalid
you map the PrivateKey type and curve to an appropriate JOSE algorithm (e.g.,
RSA->PS256/RS256 per your policy, EC with secp256r1->ES256, secp256k1->ES256K,
Ed25519->EdDSA) using SignatureProviderEnum resolution logic rather than using
privateKey.getAlgorithm() directly; apply the same change to the other fallback
block around lines 740-743 and ensure you call SignatureProviderEnum (or a new
helper) to produce a valid JOSE identifier for signing.
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/EcCryptomanagerServiceImpl.java-323-325 (1)

323-325: ⚠️ Potential issue | 🟠 Major

Use the passed provider instead of hardcoding "BC" for key reconstruction.

Line 324 ignores the provider argument and always uses BC. This can fail in deployments where BC is not registered or where provider consistency with keystore is required.

💡 Proposed fix
-            KeyFactory keyFactory = KeyFactory.getInstance(algo, BC_PROVIDER);
+            String keyFactoryProvider = (provider == null || provider.isBlank()) ? BC_PROVIDER : provider;
+            KeyFactory keyFactory = KeyFactory.getInstance(algo, keyFactoryProvider);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/EcCryptomanagerServiceImpl.java`
around lines 323 - 325, The code is hardcoding the BouncyCastle provider when
reconstructing the key; change KeyFactory.getInstance(algo, BC_PROVIDER) to use
the method parameter/provider instance instead (e.g.,
KeyFactory.getInstance(algo, provider)) so the passed-in provider argument is
used for key reconstruction in EcCryptomanagerServiceImpl (around the KeyFactory
creation that precedes X509EncodedKeySpec ephemeralPublicKeyBytes).
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/service/impl/KeymanagerServiceImpl.java-1503-1516 (1)

1503-1516: ⚠️ Potential issue | 🟠 Major

Route RSA_2048_SIGN consistently in getCertificateV2.

getCertificate(...) treats RSA_2048_SIGN as HSM-backed, but getCertificateV2 currently misses that in the HSM branch and may route to DB-store retrieval instead. This creates API inconsistency and wrong source selection for RSA signing keys.

💡 Proposed fix
 		} else if ((appId.equalsIgnoreCase(signApplicationid) && refId.isPresent()
 				&& refId.get().equals(certificateSignRefID)) ||
 				(refId.isPresent() && refId.get().equals(KeyReferenceIdConsts.EC_SECP256K1_SIGN.name())) ||
 				(refId.isPresent() && refId.get().equals(KeyReferenceIdConsts.EC_SECP256R1_SIGN.name())) ||
 				(refId.isPresent() && refId.get().equals(KeyReferenceIdConsts.ED25519_SIGN.name())
-						&& ed25519SupportFlag)) {
+						&& ed25519SupportFlag) ||
+                (refId.isPresent() && refId.get().equals(KeyReferenceIdConsts.RSA_2048_SIGN.name()))) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/service/impl/KeymanagerServiceImpl.java`
around lines 1503 - 1516, getCertificateV2 incorrectly omits treating
RSA_2048_SIGN as an HSM-backed signing key and thus can fall through to DB
retrieval; modify the HSM-branch condition in getCertificateV2 (the same branch
that calls getCertificateFromHSM) to also check for the RSA_2048_SIGN key
reference (or the appropriate KeyReferenceIdConsts/RSA_2048_SIGN constant and
certificateSignRefID like getCertificate does), so when appId equals
signApplicationid and refId matches RSA_2048_SIGN (or
refId.get().equals(corresponding enum name)) it routes to getCertificateFromHSM
rather than getRSACertificateFromDBStore.
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/EcCryptomanagerServiceImpl.java-153-160 (1)

153-160: ⚠️ Potential issue | 🟠 Major

Validate payload bounds before IV/ciphertext extraction.

Line 158 assumes encryptedData.length >= GCM_NONCE_LENGTH. Malformed input can throw runtime ArrayIndexOutOfBoundsException and bypass your mapped crypto exceptions.

💡 Proposed fix
             int splitterIndex = 0;
             splitterIndex = CryptoUtil.getSplitterIndex(data, splitterIndex, keySplitter);
+            if (splitterIndex <= 0 || splitterIndex >= data.length) {
+                throw new InvalidKeyException(
+                        SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorCode(),
+                        SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage());
+            }
@@
             byte[] encryptedData = Arrays.copyOfRange(data, 0, splitterIndex);
             byte[] ephemeralPublicKeyBytes = Arrays.copyOfRange(data, splitterIndex + keySplitterBytes.length, data.length);
+            if (encryptedData.length <= CryptomanagerConstant.GCM_NONCE_LENGTH) {
+                throw new InvalidKeyException(
+                        SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorCode(),
+                        SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage());
+            }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/EcCryptomanagerServiceImpl.java`
around lines 153 - 160, In EcCryptomanagerServiceImpl, before extracting IV and
ciphertext from encryptedData (using CryptomanagerConstant.GCM_NONCE_LENGTH),
validate that encryptedData.length >= GCM_NONCE_LENGTH + 1 (or at least >=
GCM_NONCE_LENGTH) and that splitterIndex and keySplitterBytes boundaries
produced a non-empty encryptedData; if the check fails, throw the mapped crypto
exception used elsewhere (rather than letting ArrayIndexOutOfBoundsException
escape). Update the logic around variables encryptedData, iv and cipherText to
perform this bounds check and raise the proper domain exception with a clear
message.
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/util/CryptomanagerUtils.java-479-480 (1)

479-480: ⚠️ Potential issue | 🟠 Major

Avoid logging the full DB key-store entity.

Line 479 logs dbKeyStore.toString(), which can expose key/certificate metadata in logs. Prefer logging only minimal identifiers (alias/app/ref).

💡 Proposed fix
-                LOGGER.error(KeymanagerConstant.SESSIONID, KeymanagerConstant.KEYFROMDB, dbKeyStore.toString(),
+                LOGGER.error(KeymanagerConstant.SESSIONID, KeymanagerConstant.KEYFROMDB, dbKeyStore.getAlias(),
                         "Key in DBStore does not exist for this alias. Throwing exception");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/util/CryptomanagerUtils.java`
around lines 479 - 480, The LOGGER.error call in CryptomanagerUtils is logging
dbKeyStore.toString(), which may expose sensitive key/certificate metadata;
update the call to remove the full entity and instead log only minimal
non-sensitive identifiers (for example use dbKeyStore.getAlias(),
dbKeyStore.getApplicationId()/getAppCode() and
dbKeyStore.getReferenceId()/getRef() or the actual identifier accessor names in
the DB entity) alongside KeymanagerConstant.SESSIONID and
KeymanagerConstant.KEYFROMDB; ensure no key material or full toString() output
is included and keep the message descriptive (e.g., "Key in DBStore does not
exist for alias") while retaining existing exception flow in CryptomanagerUtils.
🟡 Minor comments (5)
kernel/keys-algorithm-migrator/pom.xml-200-200 (1)

200-200: ⚠️ Potential issue | 🟡 Minor

Fix SCM connection URL typo.

Line 200 uses mosip/keyanager.git; this should be mosip/keymanager.git to keep SCM metadata valid.

🔧 Proposed fix
-		<connection>scm:git:git://github.com/mosip/keyanager.git</connection>
+		<connection>scm:git:git://github.com/mosip/keymanager.git</connection>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kernel/keys-algorithm-migrator/pom.xml` at line 200, Update the SCM
connection URL in the pom's <connection> element: replace the incorrect
repository name "mosip/keyanager.git" with the correct "mosip/keymanager.git" so
the SCM metadata reads "scm:git:git://github.com/mosip/keymanager.git".
kernel/keys-algorithm-migrator/configure_start.sh-9-19 (1)

9-19: ⚠️ Potential issue | 🟡 Minor

Fail fast if Artifactory URL is missing.

artifactory_url_env is consumed without validation. Add an explicit pre-check so startup fails with a clear message instead of an opaque wget error.

Proposed fix
+ : "${artifactory_url_env:?artifactory_url_env must be set}"
+
 echo "Download the client from $artifactory_url_env"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kernel/keys-algorithm-migrator/configure_start.sh` around lines 9 - 19, The
script uses artifactory_url_env without validation, so add a pre-check before
any use (before the echo "Download the client..." and before building the wget
URL) that verifies artifactory_url_env is set and non-empty; if it's missing,
print a clear error to stderr and exit with a non-zero status so startup fails
fast. Reference the environment variable artifactory_url_env and the wget
invocation (wget "$artifactory_url_env/$zip_path") when adding the check; keep
the existing FILE_NAME and DIR_NAME handling unchanged but ensure the check runs
first.
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/signature/service/impl/CoseSignatureServiceImpl.java-478-482 (1)

478-482: ⚠️ Potential issue | 🟡 Minor

Missing spaces in log messages produce unreadable output.

The string concatenation "for appId:" + applicationId + "and refId:" + referenceId will produce output like for appId:KERNELand refId:SIGN — note no space before "and" and after the appId value.

🔧 Proposed fix
         LOGGER.info(SignatureConstant.SESSIONID, SignatureConstant.COSE_SIGN, SignatureConstant.BLANK,
-        "Getting Signature Certificate. for appId:" + applicationId + "and refId:" + referenceId);
+        "Getting Signature Certificate. for appId: " + applicationId + " and refId: " + referenceId);
         SignatureCertificate certificateResponse = keymanagerService.getSignatureCertificate(applicationId, Optional.of(referenceId), timestamp);
         LOGGER.info(SignatureConstant.SESSIONID, SignatureConstant.COSE_SIGN, SignatureConstant.BLANK,
-                "Signature Certificate Obtained. for appId:" + applicationId + "and refId:" + referenceId);
+                "Signature Certificate Obtained. for appId: " + applicationId + " and refId: " + referenceId);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/signature/service/impl/CoseSignatureServiceImpl.java`
around lines 478 - 482, The log messages in CoseSignatureServiceImpl using
LOGGER.info concatenate applicationId and referenceId without spaces; update the
two LOGGER.info calls around getSignatureCertificate (referencing LOGGER,
SignatureConstant.SESSIONID, SignatureConstant.COSE_SIGN, applicationId,
referenceId, and keymanagerService.getSignatureCertificate) to include proper
spacing/punctuation (e.g., "for appId: " and " and refId: ") so the output reads
correctly; ensure both the pre-call and post-call messages are fixed
consistently.
kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/keymanagerservice/test/controller/KeymanagerControllerTest.java-548-552 (1)

548-552: ⚠️ Potential issue | 🟡 Minor

Reinstate a response-body assertion for this endpoint test.

Line [551] only checks HTTP status now; this can miss functional regressions when response wraps errors with 200 status.

🧪 Suggested assertion strengthening
         mockMvc.perform(post("/generateSymmetricKey")
                         .contentType(MediaType.APPLICATION_JSON)
                         .content(objectMapper.writeValueAsString(request)))
-                .andExpect(status().isOk());
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.response").exists());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/keymanagerservice/test/controller/KeymanagerControllerTest.java`
around lines 548 - 552, The test KeymanagerControllerTest currently only asserts
HTTP 200 for the mockMvc.perform(post("/generateSymmetricKey")... ) call which
can miss error payloads wrapped in 200; update the assertion to validate the
response body (e.g., assert non-empty JSON and expected fields) by adding
content assertions on the mockMvc result (use
objectMapper.writeValueAsString(request) to locate the request and then assert
response content type and jsonPath or string content for the expected key
properties) so the test verifies both status and the actual returned payload.
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/constant/CryptomanagerErrorCode.java-72-72 (1)

72-72: ⚠️ Potential issue | 🟡 Minor

%S in the error message format string uppercases the substituted value — likely unintentional.

String.format treats %S as uppercase-%s, which will render the public-key algorithm name in ALL CAPS in the error message. Use %s unless the uppercase rendering is intentional.

🐛 Proposed fix
-    JWE_ENCRYPTION_NOT_SUPPORTED("KER-CRY-017", "JWE encryption is not supported for the provided (%S) public key."),
+    JWE_ENCRYPTION_NOT_SUPPORTED("KER-CRY-017", "JWE encryption is not supported for the provided (%s) public key."),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/constant/CryptomanagerErrorCode.java`
at line 72, The error message for the enum constant JWE_ENCRYPTION_NOT_SUPPORTED
in CryptomanagerErrorCode uses "%S" which forces uppercase via String.format;
change the format specifier to "%s" in the JWE_ENCRYPTION_NOT_SUPPORTED
definition so the substituted public key algorithm name is rendered with its
original casing.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c03238a and eb4b78d.

📒 Files selected for processing (46)
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/constant/CryptomanagerConstant.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/constant/CryptomanagerErrorCode.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/EcCryptomanagerService.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/CryptomanagerServiceImpl.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/EcCryptomanagerServiceImpl.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/util/CryptomanagerUtils.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keygenerator/bouncycastle/KeyGenerator.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keygenerator/bouncycastle/util/KeyGeneratorUtils.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanager/hsm/constant/KeymanagerConstant.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanager/hsm/impl/KeyStoreImpl.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanager/hsm/impl/pkcs/PKCS11KeyStoreImpl.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanager/hsm/impl/pkcs/PKCS12KeyStoreImpl.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanager/hsm/util/CertificateUtility.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/constant/KeyReferenceIdConsts.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/constant/KeymanagerConstant.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/constant/KeymanagerErrorConstant.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/controller/KeymanagerController.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/helper/PrivateKeyDecryptorHelper.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/helper/SessionKeyDecrytorHelper.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/service/KeymanagerService.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/service/impl/KeymanagerServiceImpl.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/util/KeymanagerUtil.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymigrate/service/impl/KeyMigratorServiceImpl.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/signature/constant/SignatureAlgorithmIdentifyEnum.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/signature/constant/SignatureProviderEnum.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/signature/service/impl/CoseSignatureServiceImpl.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/signature/service/impl/SignatureServiceImpl.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/signature/util/SignatureUtil.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/zkcryptoservice/service/impl/ZKCryptoManagerServiceImpl.java
  • kernel/kernel-keymanager-service/src/main/resources/application-local.properties
  • kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/cryptomanager/test/integration/CryptographicServiceIntegrationTest.java
  • kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/cryptomanager/test/service/EcCryptomanagerServeTest.java
  • kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/keymanagerservice/test/controller/KeymanagerControllerTest.java
  • kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/keymanagerservice/test/service/KeymanagerServiceImplTest.java
  • kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/keymigrate/test/KeyMigratorServiceTest.java
  • kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/zkcryptoservice/test/ZKCryptoManagerServiceTest.java
  • kernel/keys-algorithm-migrator/Dockerfile
  • kernel/keys-algorithm-migrator/README.md
  • kernel/keys-algorithm-migrator/configure_start.sh
  • kernel/keys-algorithm-migrator/pom.xml
  • kernel/keys-algorithm-migrator/src/main/java/io/mosip/kernel/migratealgorithm/MigrateKeysAlgorithmApplication.java
  • kernel/keys-algorithm-migrator/src/main/java/io/mosip/kernel/migratealgorithm/impl/ComponentKeysAlgorithmMigrator.java
  • kernel/keys-algorithm-migrator/src/main/resources/application-local.properties
  • kernel/keys-algorithm-migrator/src/main/resources/bootstrap.properties
  • kernel/keys-migrator/src/main/java/io/mosip/kernel/migrate/impl/BaseKeysMigrator.java
  • kernel/pom.xml

Signed-off-by: nagendra0721 <nagendra0718@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/util/KeymanagerUtil.java (1)

494-495: ⚠️ Potential issue | 🔴 Critical

Fix null-check guard to avoid NPE in SAN parsing.

Both guards use && and dereference altValuesMap when it is null. This will fail at runtime.

🔧 Proposed fix
-		if (altValuesMap == null && altValuesMap.isEmpty()) {
+		if (altValuesMap == null || altValuesMap.isEmpty()) {
 			return certParams;
 		}

Also applies to: 564-565

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/util/KeymanagerUtil.java`
around lines 494 - 495, The null-check guard in KeymanagerUtil is wrong: it
currently uses "altValuesMap == null && altValuesMap.isEmpty()" which
dereferences altValuesMap when null and can throw NPE; change both occurrences
to use a short-circuiting check (altValuesMap == null || altValuesMap.isEmpty())
so the method (the SAN parsing logic in KeymanagerUtil referencing altValuesMap)
returns early safely. Ensure both places mentioned (the two guards around SAN
parsing) are updated to the || form.
♻️ Duplicate comments (1)
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/CryptomanagerServiceImpl.java (1)

261-263: ⚠️ Potential issue | 🔴 Critical

Derive ECC algorithm from the certificate public key, not global config.

Using ecCurveName here can produce header/algorithm mismatch when the certificate key differs from configured default.

🔧 Proposed fix
-            String algName = ecCurveName.equals(KeymanagerConstant.ED25519_KEY_TYPE) ? KeymanagerConstant.X25519_KEY_TYPE : ecCurveName;
+            String algName = keymanagerUtil.getEcCurveName(publicKey);
+            if (KeymanagerConstant.ED25519_KEY_TYPE.equalsIgnoreCase(algName)) {
+                algName = KeymanagerConstant.X25519_KEY_TYPE;
+            }
             byte[] encryptedData = ecCryptomanagerService.asymmetricEcEncrypt(publicKey, cryptomanagerUtil.decodeBase64Data(cryptoRequestDto.getData()), null, aad, algName);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/CryptomanagerServiceImpl.java`
around lines 261 - 263, The code is using the global ecCurveName to set algName
which can mismatch the certificate's actual public key; replace usage of
ecCurveName when computing algName for the asymmetric EC encrypt call. Inspect
the provided publicKey (the certificate public key) to derive the
curve/algorithm name (e.g., inspect publicKey.getAlgorithm(), key parameters or
curve OID) and map ED25519 to X25519 as before
(KeymanagerConstant.ED25519_KEY_TYPE -> KeymanagerConstant.X25519_KEY_TYPE) to
produce algName, then call ecCryptomanagerService.asymmetricEcEncrypt(publicKey,
cryptomanagerUtil.decodeBase64Data(cryptoRequestDto.getData()), null, aad,
algName) and keep the concatByteArrays(aad, encryptedData) step unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/CryptomanagerServiceImpl.java`:
- Around line 270-272: The encrypted payload currently places concatedData (from
cryptomanagerUtil.concatCertThumbprint) before the splitter when calling
CryptoUtil.combineByteArray in CryptomanagerServiceImpl, but the ECC decrypt
parser expects thumbprint/data to be located after the splitter; change the
ordering so the splitter and headerBytes are combined first and concatedData is
appended after the splitter (i.e., invert the arguments to
CryptoUtil.combineByteArray or reorder inputs) so finalEncKeyBytes matches the
decrypt layout, then continue to encode with CryptoUtil.encodeToURLSafeBase64
and set via cryptoResponseDto.setData.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/util/KeymanagerUtil.java`:
- Around line 760-771: The code repeatedly loads SIGN trust certificates inside
the per-trust-cert loop causing redundant repository/service calls; move the
sign-cert loading logic out of that loop: call
keyAliasRepository.findByApplicationIdAndReferenceId(signApplicationid,
certificateSignRefID) once, map each signCert to its CertificateDataResponseDto
via keymanagerService.getAllCertificates(signCert.getApplicationId(),
Optional.ofNullable(signCert.getReferenceId())), convert each cert using
convertToCertificate(...) and populate intermediateTrust (or a new collection)
before entering the trustCert loop, then reuse that preloaded collection inside
the loop instead of calling findByApplicationIdAndReferenceId/getAllCertificates
repeatedly.

---

Outside diff comments:
In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/util/KeymanagerUtil.java`:
- Around line 494-495: The null-check guard in KeymanagerUtil is wrong: it
currently uses "altValuesMap == null && altValuesMap.isEmpty()" which
dereferences altValuesMap when null and can throw NPE; change both occurrences
to use a short-circuiting check (altValuesMap == null || altValuesMap.isEmpty())
so the method (the SAN parsing logic in KeymanagerUtil referencing altValuesMap)
returns early safely. Ensure both places mentioned (the two guards around SAN
parsing) are updated to the || form.

---

Duplicate comments:
In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/CryptomanagerServiceImpl.java`:
- Around line 261-263: The code is using the global ecCurveName to set algName
which can mismatch the certificate's actual public key; replace usage of
ecCurveName when computing algName for the asymmetric EC encrypt call. Inspect
the provided publicKey (the certificate public key) to derive the
curve/algorithm name (e.g., inspect publicKey.getAlgorithm(), key parameters or
curve OID) and map ED25519 to X25519 as before
(KeymanagerConstant.ED25519_KEY_TYPE -> KeymanagerConstant.X25519_KEY_TYPE) to
produce algName, then call ecCryptomanagerService.asymmetricEcEncrypt(publicKey,
cryptomanagerUtil.decodeBase64Data(cryptoRequestDto.getData()), null, aad,
algName) and keep the concatByteArrays(aad, encryptedData) step unchanged.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eb4b78d and 0e2546c.

📒 Files selected for processing (2)
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/CryptomanagerServiceImpl.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/util/KeymanagerUtil.java

Signed-off-by: nagendra0721 <nagendra0718@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (2)
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/CryptomanagerServiceImpl.java (1)

271-273: ⚠️ Potential issue | 🔴 Critical

ECC payload layout is still inverted against the decrypt parser.

Line 272 places concatedData before the splitter, but decrypt expects the ECC header/algorithm bytes before the splitter and thumbprint+ciphertext after it. This causes incorrect algorithm detection/decryption path selection.

🔧 Proposed fix
-            byte[] finalEncKeyBytes = CryptoUtil.combineByteArray(concatedData, headerBytes, keySplitter);
+            byte[] finalEncKeyBytes = CryptoUtil.combineByteArray(headerBytes, concatedData, keySplitter);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/CryptomanagerServiceImpl.java`
around lines 271 - 273, The payload bytes are being assembled in the wrong
order: replace the current combination that puts concatedData before headerBytes
(the call to CryptoUtil.combineByteArray(concatedData, headerBytes,
keySplitter)) with an order matching the decrypt parser (headerBytes first, then
keySplitter, then certThumbprint+ciphertext). Update the call in
CryptomanagerServiceImpl where concatedData is created by concatCertThumbprint
to instead call CryptoUtil.combineByteArray(headerBytes, keySplitter,
concatedData) so finalEncKeyBytes (and the subsequent
CryptoUtil.encodeToURLSafeBase64/cryptoResponseDto.setData) produce the expected
ECC header+splitter+thumbprint+ciphertext layout.
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/zkcryptoservice/service/impl/ZKCryptoManagerServiceImpl.java (1)

450-460: ⚠️ Potential issue | 🔴 Critical

NullPointerException / NoSuchElementException when no thumbprint matches — DB operations still precede the encRandomKey null-guard.

The fix proposed in the previous review has not been applied. Lines 450–453 execute unconditionally after the loop:

  • Line 451: Objects.requireNonNull(kyAlias) throws NullPointerException (with no diagnostic message) when no alias matched.
  • Line 452: dbKeyStore.get() throws NoSuchElementException if the alias isn't in the store.

The null-check at line 455 (intended to guard both) never gets a chance to fire. Move the DB lookups and certificate parsing to after the encRandomKey guard, as outlined in the prior review.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/zkcryptoservice/service/impl/ZKCryptoManagerServiceImpl.java`
around lines 450 - 460, The DB lookups and certificate parsing (calls to
keyStoreRepository.findByAlias(kyAlias),
keyAliasRepository.findById(Objects.requireNonNull(kyAlias)), using
dbKeyStore.get(), reading certificateData and calling
keymanagerUtil.convertToCertificate) must be moved so they run only after the
null/absence guard on encRandomKey; currently they execute unconditionally and
can throw NullPointerException/NoSuchElementException before the encRandomKey
check. Change the flow in ZKCryptoManagerServiceImpl: first check if
encRandomKey is null and throw the ZKCryptoException as currently written, then
perform keyStoreRepository.findByAlias(kyAlias) and
keyAliasRepository.findById(kyAlias) and parse certificateData; when unwrapping
Optionals avoid .get() and Objects.requireNonNull—use Optional.orElseThrow with
a clear exception or handle the empty case to produce meaningful errors.
🧹 Nitpick comments (1)
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/zkcryptoservice/service/impl/ZKCryptoManagerServiceImpl.java (1)

465-471: Move SymmetricKeyRequestDto construction into the RSA branch only.

symmetricKeyRequestDto is constructed unconditionally but is only consumed in the RSA path (line 469). The EC branch (lines 470–471) doesn't use it. Move it inside the RSA branch to avoid unnecessary allocation and to clarify control flow.

♻️ Proposed refactor
-        SymmetricKeyRequestDto symmetricKeyRequestDto = new SymmetricKeyRequestDto(pubKeyApplicationId,
-                localDateTimeStamp, pubKeyReferenceId, encRandomKey, true);
-
         String randomKey = x509Cert.getPublicKey().getAlgorithm().equalsIgnoreCase(KeymanagerConstant.RSA)
-                ? keyManagerService.decryptSymmetricKey(symmetricKeyRequestDto).getSymmetricKey()
+                ? keyManagerService.decryptSymmetricKey(new SymmetricKeyRequestDto(pubKeyApplicationId,
+                        localDateTimeStamp, pubKeyReferenceId, encRandomKey, true)).getSymmetricKey()
                 : CryptoUtil.encodeToURLSafeBase64(ecCryptomanagerService.asymmetricEcDecrypt(privateKey,
                         encRandomKeyBytes, null, keymanagerUtil.getEcCurveName(x509Cert.getPublicKey())));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/zkcryptoservice/service/impl/ZKCryptoManagerServiceImpl.java`
around lines 465 - 471, Move construction of SymmetricKeyRequestDto into the RSA
branch so it’s only created when needed: check
x509Cert.getPublicKey().getAlgorithm().equalsIgnoreCase(KeymanagerConstant.RSA)
and inside that branch instantiate SymmetricKeyRequestDto then call
keyManagerService.decryptSymmetricKey(...).getSymmetricKey(); keep the EC branch
using ecCryptomanagerService.asymmetricEcDecrypt(privateKey, encRandomKeyBytes,
null, keymanagerUtil.getEcCurveName(...)) unchanged. This avoids unnecessary
allocation and makes the control flow around SymmetricKeyRequestDto,
keyManagerService.decryptSymmetricKey, and
ecCryptomanagerService.asymmetricEcDecrypt explicit.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/util/CryptomanagerUtils.java`:
- Around line 460-467: Trim and case-normalize referenceId before routing:
replace direct uses of refId.get() with a normalized value (e.g., String
referenceId = refId.get().trim().toUpperCase(Locale.ROOT)) and pass that
normalized referenceId into isSignatureKeyRefId(appId, referenceId) and
getKeyFromHSM(appId, referenceId); apply the same trimming/case-folding before
any DB routing/lookup calls (the other occurrence that currently calls
isSignatureKeyRefId/getKeyFromHSM or performs DB lookup should use the same
normalized referenceId).

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/zkcryptoservice/service/impl/ZKCryptoManagerServiceImpl.java`:
- Around line 154-156: In ZKCryptoManagerServiceImpl (the warmup loop), replace
the broad "catch (Throwable e)" with a narrower "catch (Exception e)" so JVM
Errors (e.g., OutOfMemoryError, StackOverflowError) are not swallowed;
optionally add a separate "catch (Error e)" that rethrows the Error (or logs and
rethrows) to ensure fatal JVM errors propagate rather than being ignored.
- Around line 462-464: The code calls keyAliasRepository.findById(kyAlias) and
then uses keyAliasObj.get() without checking presence, which can throw
NoSuchElementException; update ZKCryptoManagerServiceImpl to check
keyAliasObj.isPresent() (or use orElseThrow with a clear exception) before
accessing getApplicationId/getReferenceId, and if absent throw or return a
controlled error (e.g., IllegalStateException or a custom exception) with a
descriptive message; ensure the subsequent call to
cryptomanagerUtil.getPrivateKeyForDecryption still uses the safely-obtained
keyAlias values and that the error path is logged or propagated consistently.

---

Duplicate comments:
In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/CryptomanagerServiceImpl.java`:
- Around line 271-273: The payload bytes are being assembled in the wrong order:
replace the current combination that puts concatedData before headerBytes (the
call to CryptoUtil.combineByteArray(concatedData, headerBytes, keySplitter))
with an order matching the decrypt parser (headerBytes first, then keySplitter,
then certThumbprint+ciphertext). Update the call in CryptomanagerServiceImpl
where concatedData is created by concatCertThumbprint to instead call
CryptoUtil.combineByteArray(headerBytes, keySplitter, concatedData) so
finalEncKeyBytes (and the subsequent
CryptoUtil.encodeToURLSafeBase64/cryptoResponseDto.setData) produce the expected
ECC header+splitter+thumbprint+ciphertext layout.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/zkcryptoservice/service/impl/ZKCryptoManagerServiceImpl.java`:
- Around line 450-460: The DB lookups and certificate parsing (calls to
keyStoreRepository.findByAlias(kyAlias),
keyAliasRepository.findById(Objects.requireNonNull(kyAlias)), using
dbKeyStore.get(), reading certificateData and calling
keymanagerUtil.convertToCertificate) must be moved so they run only after the
null/absence guard on encRandomKey; currently they execute unconditionally and
can throw NullPointerException/NoSuchElementException before the encRandomKey
check. Change the flow in ZKCryptoManagerServiceImpl: first check if
encRandomKey is null and throw the ZKCryptoException as currently written, then
perform keyStoreRepository.findByAlias(kyAlias) and
keyAliasRepository.findById(kyAlias) and parse certificateData; when unwrapping
Optionals avoid .get() and Objects.requireNonNull—use Optional.orElseThrow with
a clear exception or handle the empty case to produce meaningful errors.

---

Nitpick comments:
In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/zkcryptoservice/service/impl/ZKCryptoManagerServiceImpl.java`:
- Around line 465-471: Move construction of SymmetricKeyRequestDto into the RSA
branch so it’s only created when needed: check
x509Cert.getPublicKey().getAlgorithm().equalsIgnoreCase(KeymanagerConstant.RSA)
and inside that branch instantiate SymmetricKeyRequestDto then call
keyManagerService.decryptSymmetricKey(...).getSymmetricKey(); keep the EC branch
using ecCryptomanagerService.asymmetricEcDecrypt(privateKey, encRandomKeyBytes,
null, keymanagerUtil.getEcCurveName(...)) unchanged. This avoids unnecessary
allocation and makes the control flow around SymmetricKeyRequestDto,
keyManagerService.decryptSymmetricKey, and
ecCryptomanagerService.asymmetricEcDecrypt explicit.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0e2546c and 6fb3ab5.

📒 Files selected for processing (3)
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/service/impl/CryptomanagerServiceImpl.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/cryptomanager/util/CryptomanagerUtils.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/zkcryptoservice/service/impl/ZKCryptoManagerServiceImpl.java

Signed-off-by: nagendra0721 <nagendra0718@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/zkcryptoservice/test/ZKCryptoManagerServiceTest.java (2)

1524-1528: Consider folding CURRENTKEYALIAS initialization into createKeyAliasMapWithKeyAliases.

Several tests repeat pubKeyAliasMap.put(KeymanagerConstant.CURRENTKEYALIAS, Collections.emptyList()). Centralizing that in the helper will reduce duplication and keep fixture shape consistent.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/zkcryptoservice/test/ZKCryptoManagerServiceTest.java`
around lines 1524 - 1528, The helper createKeyAliasMapWithKeyAliases currently
only sets KeymanagerConstant.KEYALIAS; update it to also populate
KeymanagerConstant.CURRENTKEYALIAS with Collections.emptyList() so callers no
longer need to repeatedly call
pubKeyAliasMap.put(KeymanagerConstant.CURRENTKEYALIAS, Collections.emptyList()).
Modify createKeyAliasMapWithKeyAliases to add
keyAliasMap.put(KeymanagerConstant.CURRENTKEYALIAS, Collections.emptyList()) and
then remove the duplicated pubKeyAliasMap.put(...) lines from tests that build
pubKeyAliasMap.

106-110: ECC branch intent is present, but not explicitly asserted.

You introduced ecCryptomanagerService and force an EC curve in setup, but these tests don’t explicitly verify ECC-service interaction. Add at least one assertion-driven test that proves the ECC re-encryption path invokes ecCryptomanagerService for EC keys.

Also applies to: 1548-1563

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/zkcryptoservice/test/ZKCryptoManagerServiceTest.java`
around lines 106 - 110, Add a new assertion-driven test that, with the EC branch
forced in setup, invokes the ZKCryptoManagerService re-encryption flow and
verifies the EC-specific service is used: call the same method under test that
triggers re-encryption on ZKCryptoManagerService (the method exercised by
existing tests), then use Mockito.verify(ecCryptomanagerService, times(1)) to
assert the expected EC method (e.g., reEncrypt/reEncryptKey or the EC-specific
operation used in your code) was called for EC keys; keep KeyAliasRepository
mocked as before and assert no unintended calls to non-EC services if
applicable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/zkcryptoservice/test/ZKCryptoManagerServiceTest.java`:
- Around line 366-377: Remove the catch block that treats NullPointerException
as an acceptable outcome in ZKCryptoManagerServiceTest and its other similar
negative-path test blocks; keep only the expect-ZKCryptoException flow for
zkReEncryptRandomKey so NPEs surface as test failures. Specifically, in the test
method(s) calling zkReEncryptRandomKey(encryptedKey) remove the catch
(NullPointerException e) branch (and its assertNotNull) so the test only catches
ZKCryptoException, and ensure any setup uses encRandomKey/kyAlias so the failure
path triggers the intended ZKCryptoException rather than masking bugs; apply the
same change to the analogous test block(s) mentioned in the comment.

---

Nitpick comments:
In
`@kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/zkcryptoservice/test/ZKCryptoManagerServiceTest.java`:
- Around line 1524-1528: The helper createKeyAliasMapWithKeyAliases currently
only sets KeymanagerConstant.KEYALIAS; update it to also populate
KeymanagerConstant.CURRENTKEYALIAS with Collections.emptyList() so callers no
longer need to repeatedly call
pubKeyAliasMap.put(KeymanagerConstant.CURRENTKEYALIAS, Collections.emptyList()).
Modify createKeyAliasMapWithKeyAliases to add
keyAliasMap.put(KeymanagerConstant.CURRENTKEYALIAS, Collections.emptyList()) and
then remove the duplicated pubKeyAliasMap.put(...) lines from tests that build
pubKeyAliasMap.
- Around line 106-110: Add a new assertion-driven test that, with the EC branch
forced in setup, invokes the ZKCryptoManagerService re-encryption flow and
verifies the EC-specific service is used: call the same method under test that
triggers re-encryption on ZKCryptoManagerService (the method exercised by
existing tests), then use Mockito.verify(ecCryptomanagerService, times(1)) to
assert the expected EC method (e.g., reEncrypt/reEncryptKey or the EC-specific
operation used in your code) was called for EC keys; keep KeyAliasRepository
mocked as before and assert no unintended calls to non-EC services if
applicable.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6fb3ab5 and 5ad0c58.

📒 Files selected for processing (1)
  • kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/zkcryptoservice/test/ZKCryptoManagerServiceTest.java

@nagendra0721 nagendra0721 changed the title Dev ecc support MOSIP-36428: ecc algorithms encryption support Feb 26, 2026
Signed-off-by: nagendra0721 <nagendra0718@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/service/impl/KeymanagerServiceImpl.java (1)

932-934: ⚠️ Potential issue | 🟠 Major

Fix incorrect logical operator to prevent NoSuchElementException.

Line 932 uses || (OR) which causes a NoSuchElementException when refId.isPresent() is false. The second condition !refId.get().trim().isEmpty() will execute and call get() on an empty Optional. Change the operator to && (AND):

Suggested fix
-		if ((refId.isPresent() || !refId.get().trim().isEmpty()) && (!appId.equalsIgnoreCase(signApplicationid) && 
+		if ((refId.isPresent() && !refId.get().trim().isEmpty()) && (!appId.equalsIgnoreCase(signApplicationid) && 
 					!refId.get().equals(certificateSignRefID))) {
 			keymanagerUtil.destoryKey(signPrivateKey);
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/service/impl/KeymanagerServiceImpl.java`
around lines 932 - 934, The if condition in KeymanagerServiceImpl uses ||
between refId.isPresent() and !refId.get().trim().isEmpty(), which can call
refId.get() when the Optional is empty; replace the OR with AND so you only call
refId.get() when present (i.e., use refId.isPresent() &&
!refId.get().trim().isEmpty()), or alternatively use a safe Optional check like
refId.map(String::trim).filter(s -> !s.isEmpty()).isPresent() before referencing
refId.get() in the subsequent checks involving appId, signApplicationid and
certificateSignRefID (the block that calls
keymanagerUtil.destoryKey(signPrivateKey)).
🧹 Nitpick comments (3)
kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/service/impl/KeymanagerServiceImpl.java (3)

376-383: Duplicate keyGenerator.getEd25519KeyPair() call can be extracted.

Lines 378 and 381 both call keyGenerator.getEd25519KeyPair() identically. The keypair generation can be moved before the conditional to reduce duplication.

♻️ Suggested refactor
 			if (referenceId.equals(KeyReferenceIdConsts.ED25519_SIGN.name()) && isSignKey) {
+                keypair = keyGenerator.getEd25519KeyPair();
                 if (eccCurve.equals(KeymanagerConstant.ED25519_KEY_TYPE)) {
-                    keypair = keyGenerator.getEd25519KeyPair();
                     certInfo = getCertificateFromHSM(applicationId, timeStamp, KeymanagerConstant.X25519_ENC_KEY_REF_ID);
                 } else {
-                    keypair = keyGenerator.getEd25519KeyPair();
                     certInfo = getCertificateFromHSM(applicationId, timeStamp, KeymanagerConstant.EMPTY);
                 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/service/impl/KeymanagerServiceImpl.java`
around lines 376 - 383, In KeymanagerServiceImpl, remove the duplicate
keyGenerator.getEd25519KeyPair() calls by invoking
keyGenerator.getEd25519KeyPair() once before the eccCurve check in the block
that handles referenceId.equals(KeyReferenceIdConsts.ED25519_SIGN.name()) &&
isSignKey; assign the resulting keypair to the existing keypair variable, then
keep the conditional only to set certInfo to
KeymanagerConstant.X25519_ENC_KEY_REF_ID when
eccCurve.equals(KeymanagerConstant.ED25519_KEY_TYPE) or to
KeymanagerConstant.EMPTY otherwise (preserving the
getCertificateFromHSM(applicationId, timeStamp, ...) calls); this refactor
touches the KeymanagerServiceImpl method containing the shown block and uses
keyGenerator, keypair, eccCurve, certInfo, getCertificateFromHSM, and
KeyReferenceIdConsts/KeymanagerConstant identifiers.

1478-1485: Exception handling loses original error context.

Catching KeymanagerServiceException and re-throwing a new one discards the original error message and stack trace. This makes debugging harder and may mask unrelated validation failures.

♻️ Suggested improvement
 		try {
 			ecKeyPairGenRequestValidator.validate(objectType, request);
 		} catch (KeymanagerServiceException e) {
 			LOGGER.error(KeymanagerConstant.SESSIONID, this.getClass().getSimpleName(), KeymanagerConstant.VALIDATE,
-					"Reference Id not supported for the provided application Id for RSA Sign Keys.");
+					"Reference Id not supported for the provided application Id for RSA Sign Keys. Original: " + e.getMessage());
 			throw new KeymanagerServiceException(KeymanagerErrorConstant.RSA_SIGN_REFERENCE_ID_NOT_SUPPORTED.getErrorCode(),
-					KeymanagerErrorConstant.RSA_SIGN_REFERENCE_ID_NOT_SUPPORTED.getErrorMessage());
+					KeymanagerErrorConstant.RSA_SIGN_REFERENCE_ID_NOT_SUPPORTED.getErrorMessage(), e);
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/service/impl/KeymanagerServiceImpl.java`
around lines 1478 - 1485, The catch block in KeymanagerServiceImpl around
ecKeyPairGenRequestValidator.validate(objectType, request) currently throws a
new KeymanagerServiceException and loses the original exception context; update
the catch to include the caught exception as the cause when rethrowing (or pass
its message), and include the original exception in the LOGGER.error call so the
stack trace is preserved (i.e., log e and throw new
KeymanagerServiceException(..., e)); keep the same error codes/messages from
KeymanagerErrorConstant.RSA_SIGN_REFERENCE_ID_NOT_SUPPORTED but attach the
original KeymanagerServiceException as the cause.

1536-1687: Significant code duplication with getCertificateFromDBStore.

This method duplicates most of getCertificateFromDBStore logic (~150 lines). Consider extracting common logic into a shared helper method with algorithm-specific callbacks or parameters to reduce maintenance burden.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/service/impl/KeymanagerServiceImpl.java`
around lines 1536 - 1687, getRSACertificateFromDBStore duplicates most of
getCertificateFromDBStore; extract the shared flow (fetching keyAlias map via
dbHelper.getKeyAliases, checking currentKeyAlias, reading KeyStore entry,
creating alias, generating KeyPair via keyGenerator.getAsymmetricKey, fetching
HSM cert via getCertificateFromHSM, computing expiry via
dbHelper.getExpiryPolicy, encrypting private key with keymanagerUtil.encryptKey,
selecting sign key with keyStore.getAsymmetricKey, building
CertificateParameters using sanHelper/getCertificateParameters*, generating cert
via CertificateUtility.generateX509Certificate, storing via
dbHelper.storeKeyInDBStore and dbHelper.storeKeyInAlias, and destroying private
key) into a single helper (e.g., createAndStoreKeypair or
buildCertificateForAlgorithm) that accepts algorithm-specific inputs/callbacks
(how to pick certInfo for X25519/Ed25519, sign algorithm selection, and any
SAN/common-name differences). Replace algorithm-branching code in
getRSACertificateFromDBStore and getCertificateFromDBStore with calls to that
helper, passing appropriate lambdas or parameters for certificate selection,
sign key alias selection, and signAlgorithm.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanager/hsm/constant/KeymanagerErrorCode.java`:
- Around line 29-31: The enum KeymanagerErrorCode has a stray trailing comma
before the semicolon and an inconsistent constant name: change the enum constant
CERTIFICATE_SIGN_NOT_SUPPORT to CERTIFICATE_SIGN_NOT_SUPPORTED (matching
ALGORITHM_NOT_SUPPORTED pattern) and remove the extraneous comma so the
declaration ends with just a semicolon; update all usages/references of
CERTIFICATE_SIGN_NOT_SUPPORT throughout the codebase to the new name.

In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/service/impl/KeymanagerServiceImpl.java`:
- Around line 1508-1516: The HSM certificate retrieval branch in
getCertificateV2 is missing handling for RSA_2048_SIGN, causing inconsistent
behavior with getCertificate; update the conditional that checks refId in
getCertificateV2 (the block that references appId, signApplicationid, refId,
certificateSignRefID, KeyReferenceIdConsts.EC_SECP256K1_SIGN,
KeyReferenceIdConsts.EC_SECP256R1_SIGN, KeyReferenceIdConsts.ED25519_SIGN and
ed25519SupportFlag) to also accept KeyReferenceIdConsts.RSA_2048_SIGN so that
the code logs the same message and calls getCertificateFromHSM(appId,
localDateTimeStamp, refId.get()) for RSA_2048_SIGN ref IDs.
- Around line 1577-1613: This method is missing a check to block key generation
for the ROOT application ID; add a validation like the existing KERNEL_APP_ID
and PARTNER_APP_ID checks (near currentKeyAlias/keyAliasMap handling in
KeymanagerServiceImpl and analogous to getCertificateFromDBStore), so if
applicationId.equalsIgnoreCase(KeymanagerConstant.ROOT_APP_ID) you log an error
via LOGGER.error (use the same session/application params pattern) and throw a
KeymanagerServiceException with
KeymanagerErrorConstant.GENERATION_NOT_ALLOWED.getErrorCode() and the formatted
GENERATION_NOT_ALLOWED message (use "Root App Id" or similar), ensuring the
ROOT_APP_ID constant and exception flow mirror the other two checks.
- Around line 1583-1598: In KeymanagerServiceImpl (inside the keyAlias.forEach
lambda) you are calling keyFromDBStore.get() without checking the Optional
returned by dbHelper.getKeyStoreFromDB(ksAlias); add an existence check and
handle the empty case instead of letting NoSuchElementException escape — for
example, if keyFromDBStore.isPresent() use get() as now, otherwise throw a
KeymanagerServiceException (with an appropriate KeymanagerErrorConstant/error
message) or handle per business logic; update the lambda to reference
keyFromDBStore.orElseThrow(...) or an explicit isPresent() branch so
masterKeyAlias and privateKeyObj access is safe.

---

Outside diff comments:
In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/service/impl/KeymanagerServiceImpl.java`:
- Around line 932-934: The if condition in KeymanagerServiceImpl uses || between
refId.isPresent() and !refId.get().trim().isEmpty(), which can call refId.get()
when the Optional is empty; replace the OR with AND so you only call refId.get()
when present (i.e., use refId.isPresent() && !refId.get().trim().isEmpty()), or
alternatively use a safe Optional check like refId.map(String::trim).filter(s ->
!s.isEmpty()).isPresent() before referencing refId.get() in the subsequent
checks involving appId, signApplicationid and certificateSignRefID (the block
that calls keymanagerUtil.destoryKey(signPrivateKey)).

---

Nitpick comments:
In
`@kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/service/impl/KeymanagerServiceImpl.java`:
- Around line 376-383: In KeymanagerServiceImpl, remove the duplicate
keyGenerator.getEd25519KeyPair() calls by invoking
keyGenerator.getEd25519KeyPair() once before the eccCurve check in the block
that handles referenceId.equals(KeyReferenceIdConsts.ED25519_SIGN.name()) &&
isSignKey; assign the resulting keypair to the existing keypair variable, then
keep the conditional only to set certInfo to
KeymanagerConstant.X25519_ENC_KEY_REF_ID when
eccCurve.equals(KeymanagerConstant.ED25519_KEY_TYPE) or to
KeymanagerConstant.EMPTY otherwise (preserving the
getCertificateFromHSM(applicationId, timeStamp, ...) calls); this refactor
touches the KeymanagerServiceImpl method containing the shown block and uses
keyGenerator, keypair, eccCurve, certInfo, getCertificateFromHSM, and
KeyReferenceIdConsts/KeymanagerConstant identifiers.
- Around line 1478-1485: The catch block in KeymanagerServiceImpl around
ecKeyPairGenRequestValidator.validate(objectType, request) currently throws a
new KeymanagerServiceException and loses the original exception context; update
the catch to include the caught exception as the cause when rethrowing (or pass
its message), and include the original exception in the LOGGER.error call so the
stack trace is preserved (i.e., log e and throw new
KeymanagerServiceException(..., e)); keep the same error codes/messages from
KeymanagerErrorConstant.RSA_SIGN_REFERENCE_ID_NOT_SUPPORTED but attach the
original KeymanagerServiceException as the cause.
- Around line 1536-1687: getRSACertificateFromDBStore duplicates most of
getCertificateFromDBStore; extract the shared flow (fetching keyAlias map via
dbHelper.getKeyAliases, checking currentKeyAlias, reading KeyStore entry,
creating alias, generating KeyPair via keyGenerator.getAsymmetricKey, fetching
HSM cert via getCertificateFromHSM, computing expiry via
dbHelper.getExpiryPolicy, encrypting private key with keymanagerUtil.encryptKey,
selecting sign key with keyStore.getAsymmetricKey, building
CertificateParameters using sanHelper/getCertificateParameters*, generating cert
via CertificateUtility.generateX509Certificate, storing via
dbHelper.storeKeyInDBStore and dbHelper.storeKeyInAlias, and destroying private
key) into a single helper (e.g., createAndStoreKeypair or
buildCertificateForAlgorithm) that accepts algorithm-specific inputs/callbacks
(how to pick certInfo for X25519/Ed25519, sign algorithm selection, and any
SAN/common-name differences). Replace algorithm-branching code in
getRSACertificateFromDBStore and getCertificateFromDBStore with calls to that
helper, passing appropriate lambdas or parameters for certificate selection,
sign key alias selection, and signAlgorithm.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5ad0c58 and 089a0b6.

📒 Files selected for processing (3)
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanager/hsm/constant/KeymanagerErrorCode.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanager/hsm/util/CertificateUtility.java
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanagerservice/service/impl/KeymanagerServiceImpl.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keymanager/hsm/util/CertificateUtility.java

Signed-off-by: nagendra0721 <nagendra0718@gmail.com>
Signed-off-by: nagendra0721 <nagendra0718@gmail.com>
Signed-off-by: nagendra0721 <nagendra0718@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant