-
Notifications
You must be signed in to change notification settings - Fork 82
MOSIP-36428: ecc encryption support #514
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package io.mosip.kernel.cryptomanager.service; | ||
|
|
||
| import java.security.PrivateKey; | ||
| import java.security.PublicKey; | ||
|
|
||
| public interface EcCryptomanagerService { | ||
|
|
||
| /** | ||
| * | ||
| * Encrypts data using an asymmetric EC public key. | ||
| * | ||
| * @param publicKey the public key to use for encryption | ||
| * @param data the data to encrypt | ||
| * @param iv the initialization vector (IV) for encryption | ||
| * @param aad additional authenticated data (AAD) | ||
| * @return the encrypted data | ||
| */ | ||
| public byte[] asymmetricEcEncrypt(PublicKey publicKey, byte[] data, byte[] iv, byte[] aad, String algorithmName); | ||
|
|
||
| /** | ||
| * | ||
| * Encrypts data using an asymmetric EC public key with a specified curve name. | ||
| * | ||
| * @param publicKey the public key to use for encryption | ||
| * @param data the data to encrypt | ||
| * @param curveName the name of the elliptic curve used | ||
| * @return the encrypted data | ||
| */ | ||
| public byte[] asymmetricEcEncrypt(PublicKey publicKey, byte[] data, String curveName); | ||
|
|
||
| /** | ||
| * | ||
| * Decrypts data using an asymmetric EC private key. | ||
| * | ||
| * @param privateKey the private key to use for decryption | ||
| * @param data the data to decrypt | ||
| * @param aad additional authenticated data (AAD) | ||
| * @param curveName the name of the elliptic curve used | ||
| * @return the decrypted data | ||
| */ | ||
| public byte[] asymmetricEcDecrypt(PrivateKey privateKey, byte[] data, byte[] aad, String curveName); | ||
| } |
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,11 +7,12 @@ | |||||||||||||||||||||||||||||||
| package io.mosip.kernel.cryptomanager.util; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| import java.io.IOException; | ||||||||||||||||||||||||||||||||
| import java.security.PublicKey; | ||||||||||||||||||||||||||||||||
| import java.security.SecureRandom; | ||||||||||||||||||||||||||||||||
| import java.security.*; | ||||||||||||||||||||||||||||||||
| import java.security.cert.Certificate; | ||||||||||||||||||||||||||||||||
| import java.security.cert.CertificateEncodingException; | ||||||||||||||||||||||||||||||||
| import java.security.interfaces.RSAPublicKey; | ||||||||||||||||||||||||||||||||
| import java.security.spec.InvalidKeySpecException; | ||||||||||||||||||||||||||||||||
| import java.security.spec.PKCS8EncodedKeySpec; | ||||||||||||||||||||||||||||||||
| import java.time.LocalDateTime; | ||||||||||||||||||||||||||||||||
| import java.time.format.DateTimeFormatter; | ||||||||||||||||||||||||||||||||
| import java.util.*; | ||||||||||||||||||||||||||||||||
|
|
@@ -24,6 +25,13 @@ | |||||||||||||||||||||||||||||||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||||||||||||||||||||||||||||||||
| import com.fasterxml.jackson.databind.json.JsonMapper; | ||||||||||||||||||||||||||||||||
| import com.fasterxml.jackson.module.afterburner.AfterburnerModule; | ||||||||||||||||||||||||||||||||
| import io.mosip.kernel.core.keymanager.spi.ECKeyStore; | ||||||||||||||||||||||||||||||||
| import io.mosip.kernel.core.util.DateUtils; | ||||||||||||||||||||||||||||||||
| import io.mosip.kernel.keymanagerservice.constant.KeyReferenceIdConsts; | ||||||||||||||||||||||||||||||||
| import io.mosip.kernel.keymanagerservice.constant.KeymanagerErrorConstant; | ||||||||||||||||||||||||||||||||
| import io.mosip.kernel.keymanagerservice.entity.KeyAlias; | ||||||||||||||||||||||||||||||||
| import io.mosip.kernel.keymanagerservice.exception.NoUniqueAliasException; | ||||||||||||||||||||||||||||||||
| import io.mosip.kernel.keymanagerservice.helper.PrivateKeyDecryptorHelper; | ||||||||||||||||||||||||||||||||
| import io.mosip.kernel.signature.constant.SignatureConstant; | ||||||||||||||||||||||||||||||||
| import org.apache.commons.codec.digest.DigestUtils; | ||||||||||||||||||||||||||||||||
| import org.bouncycastle.util.encoders.Hex; | ||||||||||||||||||||||||||||||||
|
|
@@ -93,6 +101,17 @@ public class CryptomanagerUtils { | |||||||||||||||||||||||||||||||
| @Value("${mosip.kernel.keymanager.jwtEncrypt.validate.json:true}") | ||||||||||||||||||||||||||||||||
| private boolean confValidateJson; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| /** The sign applicationid. */ | ||||||||||||||||||||||||||||||||
| @Value("${mosip.sign.applicationid:KERNEL}") | ||||||||||||||||||||||||||||||||
| private String signApplicationid; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| @Value("${mosip.sign-certificate-refid:SIGN}") | ||||||||||||||||||||||||||||||||
| private String certificateSignRefID; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| /** Flag to generate and store Ed25519 key in real HSM. */ | ||||||||||||||||||||||||||||||||
| @Value("${mosip.kernel.keymanager.ed25519.hsm.support.enabled:false}") | ||||||||||||||||||||||||||||||||
| private boolean ed25519SupportFlag; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| /** The key manager. */ | ||||||||||||||||||||||||||||||||
| @Autowired | ||||||||||||||||||||||||||||||||
| private KeymanagerService keyManager; | ||||||||||||||||||||||||||||||||
|
|
@@ -103,6 +122,12 @@ public class CryptomanagerUtils { | |||||||||||||||||||||||||||||||
| @Autowired | ||||||||||||||||||||||||||||||||
| private KeymanagerDBHelper dbHelper; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| @Autowired | ||||||||||||||||||||||||||||||||
| private ECKeyStore keyStore; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| @Autowired | ||||||||||||||||||||||||||||||||
| private PrivateKeyDecryptorHelper privateKeyDecryptorHelper; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||
| * Calls Key-Manager-Service to get public key of an application. | ||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||
|
|
@@ -123,7 +148,7 @@ public Certificate getCertificate(CryptomanagerRequestDto cryptomanagerRequestDt | |||||||||||||||||||||||||||||||
| * @param refId the ref id | ||||||||||||||||||||||||||||||||
| * @return the certificate data from key manager | ||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||
| private String getCertificateFromKeyManager(String appId, String refId) { | ||||||||||||||||||||||||||||||||
| public String getCertificateFromKeyManager(String appId, String refId) { | ||||||||||||||||||||||||||||||||
| return keyManager.getCertificate(appId, Optional.ofNullable(refId)).getCertificate(); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
@@ -322,13 +347,16 @@ public Certificate getCertificate(String applicationId, String referenceId) { | |||||||||||||||||||||||||||||||
| public void validateEncKeySize(Certificate encCert) { | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if (validateKeySize) { | ||||||||||||||||||||||||||||||||
| RSAPublicKey rsaPublicKey = (RSAPublicKey) encCert.getPublicKey(); | ||||||||||||||||||||||||||||||||
| if (rsaPublicKey.getModulus().bitLength() != 2048) { | ||||||||||||||||||||||||||||||||
| LOGGER.error(CryptomanagerConstant.SESSIONID, this.getClass().getSimpleName(), CryptomanagerConstant.JWT_ENCRYPT, | ||||||||||||||||||||||||||||||||
| "Not Allowed to preform encryption with Key size not equal to 2048 bit."); | ||||||||||||||||||||||||||||||||
| throw new CryptoManagerSerivceException(CryptomanagerErrorCode.ENCRYPT_NOT_ALLOWED_ERROR.getErrorCode(), | ||||||||||||||||||||||||||||||||
| CryptomanagerErrorCode.ENCRYPT_NOT_ALLOWED_ERROR.getErrorMessage()); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| String algorithmName = encCert.getPublicKey().getAlgorithm(); | ||||||||||||||||||||||||||||||||
| if (algorithmName.equalsIgnoreCase(KeymanagerConstant.RSA)) { | ||||||||||||||||||||||||||||||||
| RSAPublicKey rsaPublicKey = (RSAPublicKey) encCert.getPublicKey(); | ||||||||||||||||||||||||||||||||
| if (rsaPublicKey.getModulus().bitLength() != 2048) { | ||||||||||||||||||||||||||||||||
| LOGGER.error(CryptomanagerConstant.SESSIONID, this.getClass().getSimpleName(), CryptomanagerConstant.JWT_ENCRYPT, | ||||||||||||||||||||||||||||||||
| "Not Allowed to preform encryption with Key size not equal to 2048 bit."); | ||||||||||||||||||||||||||||||||
| throw new CryptoManagerSerivceException(CryptomanagerErrorCode.ENCRYPT_NOT_ALLOWED_ERROR.getErrorCode(), | ||||||||||||||||||||||||||||||||
| CryptomanagerErrorCode.ENCRYPT_NOT_ALLOWED_ERROR.getErrorMessage()); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
@@ -397,4 +425,126 @@ public boolean isJWSData(String data) { | |||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| public String getAlgorithmNameFromHeader(byte[] encryptedData) { | ||||||||||||||||||||||||||||||||
| int keyDelimiterIndex = 0; | ||||||||||||||||||||||||||||||||
| keyDelimiterIndex = CryptoUtil.getSplitterIndex(encryptedData, keyDelimiterIndex, keySplitter); | ||||||||||||||||||||||||||||||||
| byte[] algorithmBytes = Arrays.copyOfRange(encryptedData, 0, keyDelimiterIndex); | ||||||||||||||||||||||||||||||||
| String algorithmName; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if (Arrays.equals(algorithmBytes, CryptomanagerConstant.VERSION_EC256_R1)) { | ||||||||||||||||||||||||||||||||
| algorithmName = CryptomanagerConstant.EC_SECP256R1; | ||||||||||||||||||||||||||||||||
| } else if (Arrays.equals(algorithmBytes, CryptomanagerConstant.VERSION_EC256_K1)) { | ||||||||||||||||||||||||||||||||
| algorithmName = CryptomanagerConstant.EC_SECP256K1; | ||||||||||||||||||||||||||||||||
| } else if (Arrays.equals(algorithmBytes, CryptomanagerConstant.VERSION_EC_X25519)) { | ||||||||||||||||||||||||||||||||
| algorithmName = CryptomanagerConstant.EC_X25519; | ||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||
| algorithmName = KeymanagerConstant.RSA; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| return algorithmName; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| public Object[] getEncryptedPrivateKey(String appId, Optional<String> refId, String certThumbprint) { | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| LocalDateTime localDateTime = DateUtils.getUTCCurrentDateTime(); | ||||||||||||||||||||||||||||||||
| Map<String, List<KeyAlias>> keyAliasMap = dbHelper.getKeyAliases(appId, refId.get(), localDateTime); | ||||||||||||||||||||||||||||||||
| KeyAlias keyAlias = keyAliasMap.get(KeymanagerConstant.CURRENTKEYALIAS).getFirst(); | ||||||||||||||||||||||||||||||||
|
Comment on lines
+447
to
+451
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potential NullPointerException. Line 451 calls 🐛 Proposed fix public Object[] getEncryptedPrivateKey(String appId, Optional<String> refId, String certThumbprint) {
LocalDateTime localDateTime = DateUtils.getUTCCurrentDateTime();
Map<String, List<KeyAlias>> keyAliasMap = dbHelper.getKeyAliases(appId, refId.get(), localDateTime);
- KeyAlias keyAlias = keyAliasMap.get(KeymanagerConstant.CURRENTKEYALIAS).getFirst();
+ List<KeyAlias> currentKeyAliasList = keyAliasMap.get(KeymanagerConstant.CURRENTKEYALIAS);
+ if (currentKeyAliasList == null || currentKeyAliasList.isEmpty()) {
+ throw new NoUniqueAliasException(KeymanagerErrorConstant.NO_UNIQUE_ALIAS.getErrorCode(),
+ KeymanagerErrorConstant.NO_UNIQUE_ALIAS.getErrorMessage());
+ }
+ KeyAlias keyAlias = currentKeyAliasList.getFirst();
String ksAlias = keyAlias.getAlias();📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||
| String ksAlias = keyAlias.getAlias(); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if (!refId.isPresent() || refId.get().trim().isEmpty()) { | ||||||||||||||||||||||||||||||||
| LOGGER.info(KeymanagerConstant.SESSIONID, KeymanagerConstant.EMPTY, KeymanagerConstant.EMPTY, | ||||||||||||||||||||||||||||||||
| "Not valid reference Id. Getting private key from HSM."); | ||||||||||||||||||||||||||||||||
| KeyStore.PrivateKeyEntry masterKeyEntry = keyStore.getAsymmetricKey(ksAlias); | ||||||||||||||||||||||||||||||||
| PrivateKey masterPrivateKey = masterKeyEntry.getPrivateKey(); | ||||||||||||||||||||||||||||||||
| Certificate masterCert = masterKeyEntry.getCertificate(); | ||||||||||||||||||||||||||||||||
| return new Object[] {masterPrivateKey, masterCert}; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
Comment on lines
+454
to
+461
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potential NPE on Optional access. Line 454 checks 🐛 Proposed fix public Object[] getEncryptedPrivateKey(String appId, Optional<String> refId, String certThumbprint) {
+ if (!refId.isPresent() || refId.get().trim().isEmpty()) {
+ LOGGER.info(KeymanagerConstant.SESSIONID, KeymanagerConstant.EMPTY, KeymanagerConstant.EMPTY,
+ "Not valid reference Id. Getting private key from HSM.");
+ // Handle HSM retrieval for empty refId case
+ LocalDateTime localDateTime = DateUtils.getUTCCurrentDateTime();
+ Map<String, List<KeyAlias>> keyAliasMap = dbHelper.getKeyAliases(appId, KeymanagerConstant.EMPTY, localDateTime);
+ // ... rest of HSM logic
+ }
LocalDateTime localDateTime = DateUtils.getUTCCurrentDateTime();
- Map<String, List<KeyAlias>> keyAliasMap = dbHelper.getKeyAliases(appId, refId.get(), localDateTime);
+ Map<String, List<KeyAlias>> keyAliasMap = dbHelper.getKeyAliases(appId, refId.orElse(KeymanagerConstant.EMPTY), localDateTime);🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| } 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)) { | ||||||||||||||||||||||||||||||||
| LOGGER.info(KeymanagerConstant.SESSIONID, KeymanagerConstant.EMPTY, KeymanagerConstant.EMPTY, | ||||||||||||||||||||||||||||||||
| "Reference Id is present and it is " + refId.get() + " Signature Key ref Id. Getting private key from HSM."); | ||||||||||||||||||||||||||||||||
| KeyStore.PrivateKeyEntry masterKeyEntry = keyStore.getAsymmetricKey(ksAlias); | ||||||||||||||||||||||||||||||||
| PrivateKey masterPrivateKey = masterKeyEntry.getPrivateKey(); | ||||||||||||||||||||||||||||||||
| Certificate masterCert = masterKeyEntry.getCertificate(); | ||||||||||||||||||||||||||||||||
| return new Object[] {masterPrivateKey, masterCert}; | ||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||
| LOGGER.info(KeymanagerConstant.SESSIONID, KeymanagerConstant.EMPTY, KeymanagerConstant.EMPTY, | ||||||||||||||||||||||||||||||||
| "Reference Id is present. Will get Certificate from DB store"); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| String referenceId = refId.get(); | ||||||||||||||||||||||||||||||||
| io.mosip.kernel.keymanagerservice.entity.KeyStore dbKeyStore = privateKeyDecryptorHelper.getDBKeyStoreData(certThumbprint, | ||||||||||||||||||||||||||||||||
| appId, referenceId); | ||||||||||||||||||||||||||||||||
| if (dbKeyStore.getAlias().isEmpty()) { | ||||||||||||||||||||||||||||||||
| LOGGER.error(KeymanagerConstant.SESSIONID, KeymanagerConstant.KEYFROMDB, dbKeyStore.toString(), | ||||||||||||||||||||||||||||||||
| "Key in DBStore does not exist for this alias. Throwing exception"); | ||||||||||||||||||||||||||||||||
| throw new NoUniqueAliasException(KeymanagerErrorConstant.NO_UNIQUE_ALIAS.getErrorCode(), | ||||||||||||||||||||||||||||||||
| KeymanagerErrorConstant.NO_UNIQUE_ALIAS.getErrorMessage()); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| String masterKeyAlias = dbKeyStore.getMasterAlias(); | ||||||||||||||||||||||||||||||||
| String privateKeyObj = dbKeyStore.getPrivateKey(); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if (ksAlias.equals(masterKeyAlias) || privateKeyObj.equals(KeymanagerConstant.KS_PK_NA)) { | ||||||||||||||||||||||||||||||||
| LOGGER.error(KeymanagerConstant.SESSIONID, KeymanagerConstant.APPLICATIONID, null, | ||||||||||||||||||||||||||||||||
| "Not Allowed to perform decryption with other domain key."); | ||||||||||||||||||||||||||||||||
| throw new KeymanagerServiceException(KeymanagerErrorConstant.DECRYPTION_NOT_ALLOWED.getErrorCode(), | ||||||||||||||||||||||||||||||||
| KeymanagerErrorConstant.DECRYPTION_NOT_ALLOWED.getErrorMessage()); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| KeyStore.PrivateKeyEntry masterKeyEntry = keyStore.getAsymmetricKey(dbKeyStore.getMasterAlias()); | ||||||||||||||||||||||||||||||||
| PrivateKey masterPrivateKey = masterKeyEntry.getPrivateKey(); | ||||||||||||||||||||||||||||||||
| PublicKey masterPublicKey = masterKeyEntry.getCertificate().getPublicKey(); | ||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||
| * If the private key is in dbstore, then it will be first decrypted with | ||||||||||||||||||||||||||||||||
| * application's master private key from softhsm's/HSM's keystore | ||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||
| return getObjects(dbKeyStore, masterPrivateKey, masterPublicKey); | ||||||||||||||||||||||||||||||||
| } catch (Exception e) { | ||||||||||||||||||||||||||||||||
| // need confirm the error message and code | ||||||||||||||||||||||||||||||||
| LOGGER.error(KeymanagerConstant.SESSIONID, KeymanagerConstant.APPLICATIONID, null, | ||||||||||||||||||||||||||||||||
| "Error while decrypting private key from DBStore. Throwing exception", e); | ||||||||||||||||||||||||||||||||
| throw new KeymanagerServiceException(KeymanagerErrorConstant.NO_SUCH_ALGORITHM_EXCEPTION.getErrorCode(), | ||||||||||||||||||||||||||||||||
| KeymanagerErrorConstant.NO_SUCH_ALGORITHM_EXCEPTION.getErrorMessage()); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| public Object[] getObjects(io.mosip.kernel.keymanagerservice.entity.KeyStore dbKeyStore, PrivateKey masterPrivateKey, PublicKey masterPublicKey) { | ||||||||||||||||||||||||||||||||
| byte[] decryptedPrivateKey = keymanagerUtil.decryptKey(CryptoUtil.decodeURLSafeBase64(dbKeyStore.getPrivateKey()), | ||||||||||||||||||||||||||||||||
| masterPrivateKey, masterPublicKey); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| PublicKey publicKey = keymanagerUtil.convertToCertificate(dbKeyStore.getCertificateData()).getPublicKey(); | ||||||||||||||||||||||||||||||||
| String algorithmName = publicKey.getAlgorithm(); | ||||||||||||||||||||||||||||||||
| KeyFactory keyFactory = null; | ||||||||||||||||||||||||||||||||
| PrivateKey privateKey = null; | ||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||
| keyFactory = KeyFactory.getInstance(algorithmName); | ||||||||||||||||||||||||||||||||
| privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(decryptedPrivateKey)); | ||||||||||||||||||||||||||||||||
| } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { | ||||||||||||||||||||||||||||||||
| throw new RuntimeException(e); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
Comment on lines
+524
to
+529
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid throwing generic RuntimeException. Wrapping 🐛 Proposed fix try {
keyFactory = KeyFactory.getInstance(algorithmName);
privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(decryptedPrivateKey));
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
- throw new RuntimeException(e);
+ throw new KeymanagerServiceException(KeymanagerErrorConstant.CRYPTO_EXCEPTION.getErrorCode(),
+ KeymanagerErrorConstant.CRYPTO_EXCEPTION.getErrorMessage() + e.getMessage(), e);
}📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||
| Certificate certificate = keymanagerUtil.convertToCertificate(dbKeyStore.getCertificateData()); | ||||||||||||||||||||||||||||||||
| return new Object[]{privateKey, certificate}; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| public byte[] getHeaderByte(String ecCurveName) { | ||||||||||||||||||||||||||||||||
| byte[] headerBytes = new byte[0]; | ||||||||||||||||||||||||||||||||
| if (ecCurveName.equalsIgnoreCase(CryptomanagerConstant.EC_SECP256R1)) { | ||||||||||||||||||||||||||||||||
| headerBytes = CryptomanagerConstant.VERSION_EC256_R1; | ||||||||||||||||||||||||||||||||
| } else if (ecCurveName.equalsIgnoreCase(CryptomanagerConstant.EC_SECP256K1)) { | ||||||||||||||||||||||||||||||||
| headerBytes = CryptomanagerConstant.VERSION_EC256_K1; | ||||||||||||||||||||||||||||||||
| } else if (ecCurveName.equalsIgnoreCase(CryptomanagerConstant.EC_X25519)) { | ||||||||||||||||||||||||||||||||
| headerBytes = CryptomanagerConstant.VERSION_EC_X25519; | ||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||
| LOGGER.error(CryptomanagerConstant.SESSIONID, CryptomanagerConstant.ENCRYPT, CryptomanagerConstant.ENCRYPT, | ||||||||||||||||||||||||||||||||
| "Unsupported EC Curve Name: " + ecCurveName); | ||||||||||||||||||||||||||||||||
| throw new CryptoManagerSerivceException(CryptomanagerErrorCode.UNSUPPORTED_EC_CURVE.getErrorCode(), | ||||||||||||||||||||||||||||||||
| CryptomanagerErrorCode.UNSUPPORTED_EC_CURVE.getErrorMessage() + ecCurveName); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| return headerBytes; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -67,6 +67,10 @@ public class KeyGenerator { | |||||||||||||||||||||||||||||||||||||||||||||
| @Value("${mosip.kernel.keygenerator.asymmetric.ed25519.algorithm-name:Ed25519}") | ||||||||||||||||||||||||||||||||||||||||||||||
| private String asymmetricEDKeyAlgorithm; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| /** ECC algorithm curve name */ | ||||||||||||||||||||||||||||||||||||||||||||||
| @Value("${mosip.kernel.keygenerator.ecc-curve-name:SECP256R1}") | ||||||||||||||||||||||||||||||||||||||||||||||
| private String eccCurve; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| @Autowired | ||||||||||||||||||||||||||||||||||||||||||||||
| private ECKeyStore keyStore; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -84,7 +88,7 @@ public SecretKey getSymmetricKey() { | |||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||
| * This method generated Asymmetric key pairs | ||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||
| * @return {@link KeyPair} which contain public nad private key | ||||||||||||||||||||||||||||||||||||||||||||||
| * @return {@link KeyPair} which contain public and private key | ||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||
| public KeyPair getAsymmetricKey() { | ||||||||||||||||||||||||||||||||||||||||||||||
| KeyPairGenerator generator = KeyGeneratorUtils.getKeyPairGenerator(asymmetricKeyAlgorithm, asymmetricKeyLength, | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -119,4 +123,23 @@ private SecureRandom getSecureRandom() { | |||||||||||||||||||||||||||||||||||||||||||||
| return secureRandom; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||
| * This method generated Asymmetric key pairs for ECC | ||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||
| * @return {@link KeyPair} which contain public and private key | ||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||
| public KeyPair getECKeyPair() { | ||||||||||||||||||||||||||||||||||||||||||||||
| KeyPairGenerator generator = KeyGeneratorUtils.getECKeyPairGenerator(asymmetricKeyAlgorithm, eccCurve, getSecureRandom()); | ||||||||||||||||||||||||||||||||||||||||||||||
| return generator.generateKeyPair(); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+126
to
+134
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's find the KeyGenerator file and examine its full context
fd "KeyGenerator.java" -t f --path "*keygenerator*"Repository: mosip/keymanager Length of output: 293 🏁 Script executed: # Search for asymmetricKeyAlgorithm configuration in properties/yaml files
rg "asymmetric-algorithm-name|asymmetricKeyAlgorithm" -t properties -t yaml -t yml -A 2 -B 2Repository: mosip/keymanager Length of output: 94 🏁 Script executed: # Find KeyGeneratorUtils to understand how it handles the algorithm parameter
fd "KeyGeneratorUtils.java" -t fRepository: mosip/keymanager Length of output: 176 🏁 Script executed: # Find KeyGenerator file correctly
find . -name "KeyGenerator.java" -type f | grep keygeneratorRepository: mosip/keymanager Length of output: 168 🏁 Script executed: # Read KeyGeneratorUtils to understand the getECKeyPairGenerator method
cat -n kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keygenerator/bouncycastle/util/KeyGeneratorUtils.javaRepository: mosip/keymanager Length of output: 7465 🏁 Script executed: # Search for configuration files with algorithm properties using correct syntax
rg "asymmetric.*algorithm|ecKeyAlgorithm" -g "*.properties" -g "*.yml" -g "*.yaml" -A 2Repository: mosip/keymanager Length of output: 3721 🏁 Script executed: # Read the KeyGenerator.java file to understand the full context
cat -n ./kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/keygenerator/bouncycastle/KeyGenerator.javaRepository: mosip/keymanager Length of output: 5369 🏁 Script executed: # Search for usages of getECKeyPair method
rg "getECKeyPair" -B 3 -A 3Repository: mosip/keymanager Length of output: 3577 🏁 Script executed: # Search for tests related to getECKeyPair to see if this code path is tested
find . -name "*.java" -type f -path "*/test/*" | xargs rg "getECKeyPair|KeyGenerator" | head -20Repository: mosip/keymanager Length of output: 3677 🏁 Script executed: # Check if there are any tests for KeyGenerator class
find . -name "*KeyGeneratorTest*.java" -o -name "*KeyGenerator*Test.java"Repository: mosip/keymanager Length of output: 304 🏁 Script executed: # Read the KeyGeneratorTest to see if getECKeyPair is tested
cat -n ./kernel/kernel-keymanager-service/src/test/java/io/mosip/kernel/keygenerator/bouncycastle/test/KeyGeneratorTest.javaRepository: mosip/keymanager Length of output: 4652 🏁 Script executed: # Verify that KeyPairGenerator.getInstance("RSA") with ECGenParameterSpec would fail
# by checking Java security specifications - let's also check if there's any wrapper logic
rg "getECKeyPairGenerator" -B 5 -A 10Repository: mosip/keymanager Length of output: 5163 🏁 Script executed: # Check if there's any special handling in BouncyCastle for this scenario
rg "getInstance.*RSA|getInstance.*EC" kernel/kernel-keymanager-service/src/main/java -A 2Repository: mosip/keymanager Length of output: 7971 Fix EC key generation: use dedicated algorithm property instead of RSA-configured The method passes Add a dedicated Proposed fix+ /** ECC algorithm name */
+ `@Value`("${mosip.kernel.keygenerator.ec-algorithm-name:EC}")
+ private String ecKeyAlgorithm;
+
/**
* This method generated Asymmetric key pairs for ECC
*
* `@return` {`@link` KeyPair} which contain public and private key
*/
public KeyPair getECKeyPair() {
- KeyPairGenerator generator = KeyGeneratorUtils.getECKeyPairGenerator(asymmetricKeyAlgorithm, eccCurve, getSecureRandom());
+ KeyPairGenerator generator = KeyGeneratorUtils.getECKeyPairGenerator(ecKeyAlgorithm, eccCurve, getSecureRandom());
return generator.generateKeyPair();
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||
| * This method generated Asymmetric key pairs for X25519 | ||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||
| * @return {@link java.security.KeyPair} which contain public and private | ||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||
| public KeyPair getX25519KeyPair() { | ||||||||||||||||||||||||||||||||||||||||||||||
| KeyPairGenerator generator = KeyGeneratorUtils.getX25519KeyPairGenerator(getSecureRandom()); | ||||||||||||||||||||||||||||||||||||||||||||||
| return generator.generateKeyPair(); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate configuration fields.
signApplicationid(Line 106) duplicatessignApplicationId(Line 96). This creates confusion and maintenance burden. Use a single field.♻️ Proposed fix
Then update usages on lines 462-463 to use
signApplicationIdandsignRefIdinstead.🤖 Prompt for AI Agents