diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 9d2ec160..33481ac7 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,7 +1,7 @@ [package] org = "ballerina" name = "crypto" -version = "2.5.0" +version = "2.6.0" authors = ["Ballerina"] keywords = ["security", "hash", "hmac", "sign", "encrypt", "decrypt", "private key", "public key"] repository = "https://github.com/ballerina-platform/module-ballerina-crypto" @@ -15,8 +15,8 @@ graalvmCompatible = true [[platform.java17.dependency]] groupId = "io.ballerina.stdlib" artifactId = "crypto-native" -version = "2.5.0" -path = "../native/build/libs/crypto-native-2.5.0.jar" +version = "2.6.0" +path = "../native/build/libs/crypto-native-2.6.0-SNAPSHOT.jar" [[platform.java17.dependency]] groupId = "org.bouncycastle" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index b5e5422c..c0151c26 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -10,7 +10,7 @@ distribution-version = "2201.8.0" [[package]] org = "ballerina" name = "crypto" -version = "2.5.0" +version = "2.6.0" dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "test"}, diff --git a/ballerina/private_public_key.bal b/ballerina/private_public_key.bal index 53447a1a..a667388f 100644 --- a/ballerina/private_public_key.bal +++ b/ballerina/private_public_key.bal @@ -96,6 +96,24 @@ public isolated function decodeRsaPrivateKeyFromKeyStore(KeyStore keyStore, stri 'class: "io.ballerina.stdlib.crypto.nativeimpl.Decode" } external; +# Decodes the EC private key from the given PKCS#12 archive file. +# ```ballerina +# crypto:KeyStore keyStore = { +# path: "/path/to/keyStore.p12", +# password: "keyStorePassword" +# }; +# crypto:PrivateKey privateKey = check crypto:decodeEcPrivateKeyFromKeyStore(keyStore, "keyAlias", "keyPassword"); +# ``` +# +# + keyStore - KeyStore configurations +# + keyAlias - Key alias +# + keyPassword - Key password +# + return - Reference to the private key or else a `crypto:Error` if the private key was unreadable +public isolated function decodeEcPrivateKeyFromKeyStore(KeyStore keyStore, string keyAlias, string keyPassword) + returns PrivateKey|Error = @java:Method { + 'class: "io.ballerina.stdlib.crypto.nativeimpl.Decode" +} external; + # Decodes the RSA private key from the given private key and private key password. # ```ballerina # string keyFile = "/path/to/private.key"; @@ -127,6 +145,23 @@ public isolated function decodeRsaPublicKeyFromTrustStore(TrustStore trustStore, 'class: "io.ballerina.stdlib.crypto.nativeimpl.Decode" } external; +# Decodes the EC public key from the given PKCS#12 archive file. +# ```ballerina +# crypto:TrustStore trustStore = { +# path: "/path/tp/truststore.p12", +# password: "truststorePassword" +# }; +# crypto:PublicKey publicKey = check crypto:decodeEcPublicKeyFromTrustStore(trustStore, "keyAlias"); +# ``` +# +# + trustStore - TrustStore configurations +# + keyAlias - Key alias +# + return - Reference to the public key or else a `crypto:Error` if the public key was unreadable +public isolated function decodeEcPublicKeyFromTrustStore(TrustStore trustStore, string keyAlias) + returns PublicKey|Error = @java:Method { + 'class: "io.ballerina.stdlib.crypto.nativeimpl.Decode" +} external; + # Decodes the RSA public key from the given public certificate file. # ```ballerina # string certFile = "/path/to/public.cert"; diff --git a/ballerina/sign_verify.bal b/ballerina/sign_verify.bal index 11b1e456..3f45f2a8 100644 --- a/ballerina/sign_verify.bal +++ b/ballerina/sign_verify.bal @@ -116,6 +116,26 @@ public isolated function signRsaSha512(byte[] input, PrivateKey privateKey) retu 'class: "io.ballerina.stdlib.crypto.nativeimpl.Sign" } external; +# Returns the SHA384withECDSA based signature value for the given data. +# ```ballerina +# string input = "Hello Ballerina"; +# byte[] data = input.toBytes(); +# crypto:KeyStore keyStore = { +# path: "/path/to/keyStore.p12", +# password: "keyStorePassword" +# }; +# crypto:PrivateKey privateKey = check crypto:decodeEcPrivateKeyFromKeyStore(keyStore, "keyAlias", "keyPassword"); +# byte[] signature = check crypto:signSha384withEcdsa(data, privateKey); +# ``` +# +# + input - The content to be signed +# + privateKey - Private key used for signing +# + return - The generated signature or else a `crypto:Error` if the private key is invalid +public isolated function signSha384withEcdsa(byte[] input, PrivateKey privateKey) returns byte[]|Error = @java:Method { + name: "signSha384withEcdsa", + 'class: "io.ballerina.stdlib.crypto.nativeimpl.Sign" +} external; + # Verifies the RSA-MD5 based signature. # ```ballerina # string input = "Hello Ballerina"; @@ -235,3 +255,27 @@ public isolated function verifyRsaSha512Signature(byte[] data, byte[] signature, name: "verifyRsaSha512Signature", 'class: "io.ballerina.stdlib.crypto.nativeimpl.Sign" } external; + +# Verifies the SHA384withECDSA based signature. +# ```ballerina +# string input = "Hello Ballerina"; +# byte[] data = input.toBytes(); +# crypto:KeyStore keyStore = { +# path: "/path/to/keyStore.p12", +# password: "keyStorePassword" +# }; +# crypto:PrivateKey privateKey = check crypto:decodeEcPrivateKeyFromKeyStore(keyStore, "keyAlias", "keyPassword"); +# byte[] signature = check crypto:signSha384withEcdsa(data, privateKey); +# crypto:PublicKey publicKey = check crypto:decodeEcPublicKeyFromTrustStore(keyStore, "keyAlias"); +# boolean validity = check crypto:verifySha384withEcdsaSignature(data, signature, publicKey); +# ``` +# +# + data - The content to be verified +# + signature - Signature value +# + publicKey - Public key used for verification +# + return - Validity of the signature or else a `crypto:Error` if the public key is invalid +public isolated function verifySha384withEcdsaSignature(byte[] data, byte[] signature, PublicKey publicKey) + returns boolean|Error = @java:Method { + name: "verifySha384withEcdsaSignature", + 'class: "io.ballerina.stdlib.crypto.nativeimpl.Sign" +} external; diff --git a/ballerina/tests/resources/ec-keystore.pkcs12 b/ballerina/tests/resources/ec-keystore.pkcs12 new file mode 100644 index 00000000..a4c37176 Binary files /dev/null and b/ballerina/tests/resources/ec-keystore.pkcs12 differ diff --git a/ballerina/tests/sign_verify_test.bal b/ballerina/tests/sign_verify_test.bal index 6c161352..f80b5872 100644 --- a/ballerina/tests/sign_verify_test.bal +++ b/ballerina/tests/sign_verify_test.bal @@ -230,3 +230,72 @@ isolated function testVerifyRsaSha512() returns Error? { byte[] sha512Signature = check signRsaSha512(payload, privateKey); test:assertTrue(check verifyRsaSha512Signature(payload, sha512Signature, publicKey)); } + +@test:Config {} +isolated function testVerifySha384withEcdsa() returns Error? { + byte[] payload = "Ballerina test".toBytes(); + KeyStore keyStore = { + path: EC_KEYSTORE_PATH, + password: "ballerina" + }; + PrivateKey privateKey = check decodeEcPrivateKeyFromKeyStore(keyStore, "ec-keypair", "ballerina"); + PublicKey publicKey = check decodeEcPublicKeyFromTrustStore(keyStore, "ec-keypair"); + byte[] sha384withEcdsaSignature = check signSha384withEcdsa(payload, privateKey); + test:assertTrue(check verifySha384withEcdsaSignature(payload, sha384withEcdsaSignature, publicKey)); +} + +@test:Config {} +isolated function testDecodeRsaPrivateKeyError() returns Error? { + KeyStore keyStore = { + path: EC_KEYSTORE_PATH, + password: "ballerina" + }; + PrivateKey|Error privateKey = decodeRsaPrivateKeyFromKeyStore(keyStore, "ec-keypair", "ballerina"); + if privateKey is Error { + test:assertEquals(privateKey.message(), "Not a valid RSA key"); + } else { + test:assertFail("Expected error not found"); + } +} + +@test:Config {} +isolated function testDecodeEcPrivateKeyError() returns Error? { + KeyStore keyStore = { + path: KEYSTORE_PATH, + password: "ballerina" + }; + PrivateKey|Error privateKey = decodeEcPrivateKeyFromKeyStore(keyStore, "ballerina", "ballerina"); + if privateKey is Error { + test:assertEquals(privateKey.message(), "Not a valid EC key"); + } else { + test:assertFail("Expected error not found"); + } +} + +@test:Config {} +isolated function testDecodeEcPublicKeyError() returns Error? { + KeyStore keyStore = { + path: KEYSTORE_PATH, + password: "ballerina" + }; + PublicKey|Error publicKey = decodeEcPublicKeyFromTrustStore(keyStore, "ballerina"); + if publicKey is Error { + test:assertEquals(publicKey.message(), "Not a valid EC public key"); + } else { + test:assertFail("Expected error not found"); + } +} + +@test:Config {} +isolated function testDecodeRsaPublicKeyError() returns Error? { + KeyStore keyStore = { + path: EC_KEYSTORE_PATH, + password: "ballerina" + }; + PublicKey|Error publicKey = decodeRsaPublicKeyFromTrustStore(keyStore, "ec-keypair"); + if publicKey is Error { + test:assertEquals(publicKey.message(), "Not a valid RSA public key"); + } else { + test:assertFail("Expected error not found"); + } +} diff --git a/ballerina/tests/test_utils.bal b/ballerina/tests/test_utils.bal index adfd0522..0f2cc0e8 100644 --- a/ballerina/tests/test_utils.bal +++ b/ballerina/tests/test_utils.bal @@ -15,6 +15,7 @@ // under the License. const string KEYSTORE_PATH = "tests/resources/keyStore.p12"; +const string EC_KEYSTORE_PATH = "tests/resources/ec-keystore.pkcs12"; const string ENCRYPTED_KEY_PAIR_PATH = "tests/resources/encryptedKeyPair.pem"; const string KEY_PAIR_PATH = "tests/resources/keyPair.pem"; const string ENCRYPTED_PRIVATE_KEY_PATH = "tests/resources/encryptedPrivate.key"; diff --git a/changelog.md b/changelog.md index 80c755e3..3182dadb 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Added +- [Introduce new APIs to interact with EC private keys and public keys](https://github.com/ballerina-platform/ballerina-library/issues/5821) + ## [2.5.0] - 2023-09-15 ### Changed diff --git a/docs/spec/spec.md b/docs/spec/spec.md index 178d09b4..42ed0851 100644 --- a/docs/spec/spec.md +++ b/docs/spec/spec.md @@ -55,12 +55,14 @@ The conforming implementation of the specification is released and included in t * 6.1.3. [RSA-SHA256](#613-rsa-sha256) * 6.1.4. [RSA-SHA384](#614-rsa-sha384) * 6.1.5. [RSA-SHA512](#615-rsa-sha512) + * 6.1.6. [SHA384withECDSA](#616-sha384withecdsa) * 6.2. [Verify signature](#62-verify-signature) * 6.2.1. [RSA-MD5](#621-rsa-md5) * 6.2.2. [RSA-SHA1](#622-rsa-sha1) * 6.2.3. [RSA-SHA256](#623-rsa-sha256) * 6.2.4. [RSA-SHA384](#624-rsa-sha384) * 6.2.5. [RSA-SHA512](#625-rsa-sha512) + * 6.2.6. [SHA384withECDSA](#626-sha384withecdsa) ## 1. [Overview](#1-overview) @@ -471,6 +473,21 @@ crypto:PrivateKey privateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyS byte[] signature = check crypto:signRsaSha512(data, privateKey); ``` +#### 6.1.6. [SHA384withECDSA](#616-sha384withecdsa) + +This API can be used to create the SHA384withECDSA based signature value for the given data. + +```ballerina +string input = "Hello Ballerina"; +byte[] data = input.toBytes(); +crypto:KeyStore keyStore = { + path: "/path/to/keyStore.p12", + password: "keyStorePassword" +}; +crypto:PrivateKey privateKey = check crypto:decodeEcPrivateKeyFromKeyStore(keyStore, "keyAlias", "keyPassword"); +byte[] signature = check crypto:signSha384withEcdsa(data, privateKey); +``` + ### 6.2. [Verify signature](#62-verify-signature) #### 6.2.1. [RSA-MD5](#621-rsa-md5) @@ -557,3 +574,20 @@ byte[] signature = check crypto:signRsaSha512(data, privateKey); crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, "keyAlias"); boolean validity = check crypto:verifyRsaSha512Signature(data, signature, publicKey); ``` + +#### 6.2.6. [SHA384withECDSA](#626-sha384withecdsa) + +This API can be used to verify the SHA384withECDSA based signature. + +```ballerina +string input = "Hello Ballerina"; +byte[] data = input.toBytes(); +crypto:KeyStore keyStore = { + path: "/path/to/keyStore.p12", + password: "keyStorePassword" +}; +crypto:PrivateKey privateKey = check crypto:decodeEcPrivateKeyFromKeyStore(keyStore, "keyAlias", "keyPassword"); +byte[] signature = check crypto:signSha384withEcdsa(data, privateKey); +crypto:PublicKey publicKey = check crypto:decodeEcPublicKeyFromTrustStore(keyStore, "keyAlias"); +boolean validity = check crypto:verifySha384withEcdsaSignature(data, signature, publicKey); +``` diff --git a/gradle.properties b/gradle.properties index ae93c144..7be0f24c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.caching=true group=io.ballerina.stdlib -version=2.5.1-SNAPSHOT +version=2.6.0-SNAPSHOT puppycrawlCheckstyleVersion=10.12.0 bouncycastleVersion=1.74 githubSpotbugsVersion=5.0.14 diff --git a/native/src/main/java/io/ballerina/stdlib/crypto/Constants.java b/native/src/main/java/io/ballerina/stdlib/crypto/Constants.java index 65af6ec7..0af54417 100644 --- a/native/src/main/java/io/ballerina/stdlib/crypto/Constants.java +++ b/native/src/main/java/io/ballerina/stdlib/crypto/Constants.java @@ -42,6 +42,8 @@ private Constants() {} // Native data key for private key within the PrivateKey record. public static final String NATIVE_DATA_PRIVATE_KEY = "NATIVE_DATA_PRIVATE_KEY"; + public static final String NATIVE_DATA_EC_PRIVATE_KEY = "NATIVE_DATA_EC_PRIVATE_KEY"; + // Native data key for private key within the PublicKey record. public static final String NATIVE_DATA_PUBLIC_KEY = "NATIVE_DATA_PUBLIC_KEY"; @@ -97,6 +99,9 @@ private Constants() {} // RSA key algorithm public static final String RSA_ALGORITHM = "RSA"; + // EC key algorithm + public static final String EC_ALGORITHM = "EC"; + // GMT timezone name used for X509 validity times public static final String TIMEZONE_GMT = "GMT"; diff --git a/native/src/main/java/io/ballerina/stdlib/crypto/nativeimpl/Decode.java b/native/src/main/java/io/ballerina/stdlib/crypto/nativeimpl/Decode.java index cf56b0da..059a2905 100644 --- a/native/src/main/java/io/ballerina/stdlib/crypto/nativeimpl/Decode.java +++ b/native/src/main/java/io/ballerina/stdlib/crypto/nativeimpl/Decode.java @@ -73,6 +73,24 @@ private Decode() {} public static Object decodeRsaPrivateKeyFromKeyStore(BMap keyStoreRecord, BString keyAlias, BString keyPassword) { + Object decodedPrivateKey = getPrivateKey(keyStoreRecord, keyAlias, keyPassword); + if (decodedPrivateKey instanceof PrivateKey privateKey) { + return buildRsPrivateKeyRecord(privateKey); + } + return decodedPrivateKey; + } + + public static Object decodeEcPrivateKeyFromKeyStore(BMap keyStoreRecord, BString keyAlias, + BString keyPassword) { + + Object decodedPrivateKey = getPrivateKey(keyStoreRecord, keyAlias, keyPassword); + if (decodedPrivateKey instanceof PrivateKey privateKey) { + return buildEcPrivateKeyRecord(privateKey); + } + return decodedPrivateKey; + } + + private static Object getPrivateKey(BMap keyStoreRecord, BString keyAlias, BString keyPassword) { File keyStoreFile = new File(keyStoreRecord.get(Constants.KEY_STORE_RECORD_PATH_FIELD).toString()); try (FileInputStream fileInputStream = new FileInputStream(keyStoreFile)) { KeyStore keyStore = KeyStore.getInstance(Constants.KEYSTORE_TYPE_PKCS12); @@ -84,11 +102,11 @@ public static Object decodeRsaPrivateKeyFromKeyStore(BMap keyS } PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias.getValue(), - keyPassword.getValue().toCharArray()); + keyPassword.getValue().toCharArray()); if (privateKey == null) { return CryptoUtils.createError("Key cannot be recovered by using given key alias: " + keyAlias); } - return buildPrivateKeyRecord(privateKey); + return privateKey; } catch (FileNotFoundException e) { return CryptoUtils.createError("PKCS12 KeyStore not found at: " + keyStoreFile.getAbsoluteFile()); } catch (KeyStoreException | CertificateException | IOException e) { @@ -133,7 +151,7 @@ public static Object decodeRsaPrivateKeyFromKeyFile(BString keyFilePath, Object keyFilePath.getValue()); } PrivateKey privateKey = converter.getPrivateKey(privateKeyInfo); - return buildPrivateKeyRecord(privateKey); + return buildRsPrivateKeyRecord(privateKey); } catch (FileNotFoundException e) { return CryptoUtils.createError("Key file not found at: " + privateKeyFile.getAbsoluteFile()); } catch (PKCSException | IOException e) { @@ -141,20 +159,47 @@ public static Object decodeRsaPrivateKeyFromKeyFile(BString keyFilePath, Object } } - private static Object buildPrivateKeyRecord(PrivateKey privateKey) { + private static Object buildRsPrivateKeyRecord(PrivateKey privateKey) { if (privateKey.getAlgorithm().equals(Constants.RSA_ALGORITHM)) { - BMap privateKeyRecord = ValueCreator. - createRecordValue(ModuleUtils.getModule(), Constants.PRIVATE_KEY_RECORD); - privateKeyRecord.addNativeData(Constants.NATIVE_DATA_PRIVATE_KEY, privateKey); - privateKeyRecord.put(StringUtils.fromString(Constants.PRIVATE_KEY_RECORD_ALGORITHM_FIELD), - StringUtils.fromString(privateKey.getAlgorithm())); - return privateKeyRecord; + return getPrivateKeyRecord(privateKey); } else { - return CryptoUtils.createError("Not a valid RSA key."); + return CryptoUtils.createError("Not a valid RSA key"); } } + private static Object getPrivateKeyRecord(PrivateKey privateKey) { + BMap privateKeyRecord = ValueCreator. + createRecordValue(ModuleUtils.getModule(), Constants.PRIVATE_KEY_RECORD); + privateKeyRecord.addNativeData(Constants.NATIVE_DATA_PRIVATE_KEY, privateKey); + privateKeyRecord.put(StringUtils.fromString(Constants.PRIVATE_KEY_RECORD_ALGORITHM_FIELD), + StringUtils.fromString(privateKey.getAlgorithm())); + return privateKeyRecord; + } + + private static Object buildEcPrivateKeyRecord(PrivateKey privateKey) { + if (privateKey.getAlgorithm().equals(Constants.EC_ALGORITHM)) { + return getPrivateKeyRecord(privateKey); + } + return CryptoUtils.createError("Not a valid EC key"); + } + public static Object decodeRsaPublicKeyFromTrustStore(BMap trustStoreRecord, BString keyAlias) { + Object certificate = getPublicKey(trustStoreRecord, keyAlias); + if (certificate instanceof Certificate publicKey) { + return buildRsaPublicKeyRecord(publicKey); + } + return certificate; + } + + public static Object decodeEcPublicKeyFromTrustStore(BMap trustStoreRecord, BString keyAlias) { + Object certificate = getPublicKey(trustStoreRecord, keyAlias); + if (certificate instanceof Certificate publicKey) { + return buildEcPublicKeyRecord(publicKey); + } + return certificate; + } + + private static Object getPublicKey(BMap trustStoreRecord, BString keyAlias) { File keyStoreFile = new File(trustStoreRecord.get(Constants.KEY_STORE_RECORD_PATH_FIELD).toString()); try (FileInputStream fileInputStream = new FileInputStream(keyStoreFile)) { KeyStore keyStore = KeyStore.getInstance(Constants.KEYSTORE_TYPE_PKCS12); @@ -169,7 +214,7 @@ public static Object decodeRsaPublicKeyFromTrustStore(BMap tru if (certificate == null) { return CryptoUtils.createError("Certificate cannot be recovered by using given key alias: " + keyAlias); } - return buildPublicKeyRecord(certificate); + return certificate; } catch (FileNotFoundException e) { return CryptoUtils.createError("PKCS12 KeyStore not found at: " + keyStoreFile.getAbsoluteFile()); } catch (KeyStoreException | CertificateException | IOException e) { @@ -182,7 +227,7 @@ public static Object decodeRsaPublicKeyFromCertFile(BString certFilePath) { try (FileInputStream fileInputStream = new FileInputStream(certFile)) { CertificateFactory certificateFactory = CertificateFactory.getInstance(Constants.CERTIFICATE_TYPE_X509); X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(fileInputStream); - return buildPublicKeyRecord(certificate); + return buildRsaPublicKeyRecord(certificate); } catch (FileNotFoundException e) { return CryptoUtils.createError("Certificate file not found at: " + certFile.getAbsolutePath()); } catch (CertificateException | IOException e) { @@ -190,7 +235,40 @@ public static Object decodeRsaPublicKeyFromCertFile(BString certFilePath) { } } - private static Object buildPublicKeyRecord(Certificate certificate) { + private static Object buildRsaPublicKeyRecord(Certificate certificate) { + BMap certificateBMap = enrichPublicKeyInfo(certificate); + PublicKey publicKey = certificate.getPublicKey(); + if (publicKey.getAlgorithm().equals(Constants.RSA_ALGORITHM)) { + return getPublicKeyRecord(certificate, certificateBMap, publicKey); + } + return CryptoUtils.createError("Not a valid RSA public key"); + } + + private static Object buildEcPublicKeyRecord(Certificate certificate) { + BMap certificateBMap = enrichPublicKeyInfo(certificate); + PublicKey publicKey = certificate.getPublicKey(); + if (publicKey.getAlgorithm().equals(Constants.EC_ALGORITHM)) { + return getPublicKeyRecord(certificate, certificateBMap, publicKey); + } + return CryptoUtils.createError("Not a valid EC public key"); + } + + private static Object getPublicKeyRecord(Certificate certificate, BMap certificateBMap, + PublicKey publicKey) { + BMap publicKeyMap = ValueCreator. + createRecordValue(ModuleUtils.getModule(), Constants.PUBLIC_KEY_RECORD); + publicKeyMap.addNativeData(Constants.NATIVE_DATA_PUBLIC_KEY, publicKey); + publicKeyMap.addNativeData(Constants.NATIVE_DATA_PUBLIC_KEY_CERTIFICATE, certificate); + publicKeyMap.put(StringUtils.fromString(Constants.PUBLIC_KEY_RECORD_ALGORITHM_FIELD), + StringUtils.fromString(publicKey.getAlgorithm())); + if (certificateBMap.size() > 0) { + publicKeyMap.put(StringUtils.fromString(Constants.PUBLIC_KEY_RECORD_CERTIFICATE_FIELD), + certificateBMap); + } + return publicKeyMap; + } + + private static BMap enrichPublicKeyInfo(Certificate certificate) { BMap certificateBMap = ValueCreator. createRecordValue(ModuleUtils.getModule(), Constants.CERTIFICATE_RECORD); if (certificate instanceof X509Certificate) { @@ -214,22 +292,7 @@ private static Object buildPublicKeyRecord(Certificate certificate) { certificateBMap.put(StringUtils.fromString(Constants.CERTIFICATE_RECORD_SIGNATURE_ALG_FIELD), StringUtils.fromString(x509Certificate.getSigAlgName())); } - PublicKey publicKey = certificate.getPublicKey(); - if (publicKey.getAlgorithm().equals(Constants.RSA_ALGORITHM)) { - BMap publicKeyMap = ValueCreator. - createRecordValue(ModuleUtils.getModule(), Constants.PUBLIC_KEY_RECORD); - publicKeyMap.addNativeData(Constants.NATIVE_DATA_PUBLIC_KEY, publicKey); - publicKeyMap.addNativeData(Constants.NATIVE_DATA_PUBLIC_KEY_CERTIFICATE, certificate); - publicKeyMap.put(StringUtils.fromString(Constants.PUBLIC_KEY_RECORD_ALGORITHM_FIELD), - StringUtils.fromString(publicKey.getAlgorithm())); - if (certificateBMap.size() > 0) { - publicKeyMap.put(StringUtils.fromString(Constants.PUBLIC_KEY_RECORD_CERTIFICATE_FIELD), - certificateBMap); - } - return publicKeyMap; - } else { - return CryptoUtils.createError("Not a valid RSA key."); - } + return certificateBMap; } public static Object buildRsaPublicKey(BString modulus, BString exponent) { diff --git a/native/src/main/java/io/ballerina/stdlib/crypto/nativeimpl/Sign.java b/native/src/main/java/io/ballerina/stdlib/crypto/nativeimpl/Sign.java index 61377d3e..098c52e7 100644 --- a/native/src/main/java/io/ballerina/stdlib/crypto/nativeimpl/Sign.java +++ b/native/src/main/java/io/ballerina/stdlib/crypto/nativeimpl/Sign.java @@ -59,6 +59,12 @@ public static Object signRsaSha384(BArray inputValue, BMap privateKey) { return CryptoUtils.sign("SHA384withRSA", key, input); } + public static Object signSha384withEcdsa(BArray inputValue, BMap privateKey) { + byte[] input = inputValue.getBytes(); + PrivateKey key = (PrivateKey) privateKey.getNativeData(Constants.NATIVE_DATA_PRIVATE_KEY); + return CryptoUtils.sign("SHA384withECDSA", key, input); + } + public static Object signRsaSha512(BArray inputValue, BMap privateKey) { byte[] input = inputValue.getBytes(); PrivateKey key = (PrivateKey) privateKey.getNativeData(Constants.NATIVE_DATA_PRIVATE_KEY); @@ -104,4 +110,11 @@ public static Object verifyRsaSha512Signature(BArray dataValue, BArray signature PublicKey key = (PublicKey) publicKey.getNativeData(Constants.NATIVE_DATA_PUBLIC_KEY); return CryptoUtils.verify("SHA512withRSA", key, data, signature); } + + public static Object verifySha384withEcdsaSignature(BArray dataValue, BArray signatureValue, BMap publicKey) { + byte[] data = dataValue.getBytes(); + byte[] signature = signatureValue.getBytes(); + PublicKey key = (PublicKey) publicKey.getNativeData(Constants.NATIVE_DATA_PUBLIC_KEY); + return CryptoUtils.verify("SHA384withECDSA", key, data, signature); + } }