From b842b566e01a159e4f27155fb22b15af7193b318 Mon Sep 17 00:00:00 2001 From: bhashinee Date: Wed, 13 Dec 2023 09:09:08 +0530 Subject: [PATCH 1/4] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 212e2d02..5719577f 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -12,6 +12,7 @@ org = "ballerina" name = "crypto" version = "2.6.1" dependencies = [ + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "test"}, {org = "ballerina", name = "time"} @@ -20,6 +21,19 @@ modules = [ {org = "ballerina", packageName = "crypto", moduleName = "crypto"} ] +[[package]] +org = "ballerina" +name = "io" +version = "1.5.0" +scope = "testOnly" +dependencies = [ + {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "lang.value"} +] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] + [[package]] org = "ballerina" name = "jballerina.java" @@ -37,6 +51,15 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"} ] +[[package]] +org = "ballerina" +name = "lang.value" +version = "0.0.0" +scope = "testOnly" +dependencies = [ + {org = "ballerina", name = "jballerina.java"} +] + [[package]] org = "ballerina" name = "test" From fa94aaea6d1562a4a581ebc4e9392214434f63f7 Mon Sep 17 00:00:00 2001 From: bhashinee Date: Mon, 18 Dec 2023 11:47:56 +0530 Subject: [PATCH 2/4] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 5719577f..212e2d02 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -12,7 +12,6 @@ org = "ballerina" name = "crypto" version = "2.6.1" dependencies = [ - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "test"}, {org = "ballerina", name = "time"} @@ -21,19 +20,6 @@ modules = [ {org = "ballerina", packageName = "crypto", moduleName = "crypto"} ] -[[package]] -org = "ballerina" -name = "io" -version = "1.5.0" -scope = "testOnly" -dependencies = [ - {org = "ballerina", name = "jballerina.java"}, - {org = "ballerina", name = "lang.value"} -] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] - [[package]] org = "ballerina" name = "jballerina.java" @@ -51,15 +37,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"} ] -[[package]] -org = "ballerina" -name = "lang.value" -version = "0.0.0" -scope = "testOnly" -dependencies = [ - {org = "ballerina", name = "jballerina.java"} -] - [[package]] org = "ballerina" name = "test" From 7894019ebe40d8f821260d4a0fcb3a253a4eded0 Mon Sep 17 00:00:00 2001 From: bhashinee Date: Mon, 18 Dec 2023 11:50:08 +0530 Subject: [PATCH 3/4] Add sign and verify APIs to SHA256withECDSA --- ballerina/sign_verify.bal | 44 +++++++++++++++++++ ballerina/tests/sign_verify_test.bal | 13 ++++++ changelog.md | 2 + .../stdlib/crypto/nativeimpl/Sign.java | 13 ++++++ 4 files changed, 72 insertions(+) diff --git a/ballerina/sign_verify.bal b/ballerina/sign_verify.bal index 3f45f2a8..d45befbf 100644 --- a/ballerina/sign_verify.bal +++ b/ballerina/sign_verify.bal @@ -136,6 +136,26 @@ public isolated function signSha384withEcdsa(byte[] input, PrivateKey privateKey 'class: "io.ballerina.stdlib.crypto.nativeimpl.Sign" } external; +# Returns the SHA256withECDSA 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:signSha256withEcdsa(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 signSha256withEcdsa(byte[] input, PrivateKey privateKey) returns byte[]|Error = @java:Method { + name: "signSha256withEcdsa", + 'class: "io.ballerina.stdlib.crypto.nativeimpl.Sign" +} external; + # Verifies the RSA-MD5 based signature. # ```ballerina # string input = "Hello Ballerina"; @@ -279,3 +299,27 @@ public isolated function verifySha384withEcdsaSignature(byte[] data, byte[] sign name: "verifySha384withEcdsaSignature", 'class: "io.ballerina.stdlib.crypto.nativeimpl.Sign" } external; + +# Verifies the SHA256withECDSA 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:signSha256withEcdsa(data, privateKey); +# crypto:PublicKey publicKey = check crypto:decodeEcPublicKeyFromTrustStore(keyStore, "keyAlias"); +# boolean validity = check crypto:verifySha256withEcdsaSignature(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 verifySha256withEcdsaSignature(byte[] data, byte[] signature, PublicKey publicKey) + returns boolean|Error = @java:Method { + name: "verifySha256withEcdsaSignature", + 'class: "io.ballerina.stdlib.crypto.nativeimpl.Sign" +} external; diff --git a/ballerina/tests/sign_verify_test.bal b/ballerina/tests/sign_verify_test.bal index f80b5872..55b9d468 100644 --- a/ballerina/tests/sign_verify_test.bal +++ b/ballerina/tests/sign_verify_test.bal @@ -244,6 +244,19 @@ isolated function testVerifySha384withEcdsa() returns Error? { test:assertTrue(check verifySha384withEcdsaSignature(payload, sha384withEcdsaSignature, publicKey)); } +@test:Config {} +isolated function testVerifySha256withEcdsa() 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[] sha256withEcdsaSignature = check signSha256withEcdsa(payload, privateKey); + test:assertTrue(check verifySha256withEcdsaSignature(payload, sha256withEcdsaSignature, publicKey)); +} + @test:Config {} isolated function testDecodeRsaPrivateKeyError() returns Error? { KeyStore keyStore = { diff --git a/changelog.md b/changelog.md index bb516ad6..f6d4dd67 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +## [2.6.1] - 2023-12-08 + ### Added - [Introduce new APIs to decode private and public keys from files](https://github.com/ballerina-platform/ballerina-library/issues/5871) 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 098c52e7..cd7610da 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 @@ -65,6 +65,12 @@ public static Object signSha384withEcdsa(BArray inputValue, BMap privateKe return CryptoUtils.sign("SHA384withECDSA", key, input); } + public static Object signSha256withEcdsa(BArray inputValue, BMap privateKey) { + byte[] input = inputValue.getBytes(); + PrivateKey key = (PrivateKey) privateKey.getNativeData(Constants.NATIVE_DATA_PRIVATE_KEY); + return CryptoUtils.sign("SHA256withECDSA", key, input); + } + public static Object signRsaSha512(BArray inputValue, BMap privateKey) { byte[] input = inputValue.getBytes(); PrivateKey key = (PrivateKey) privateKey.getNativeData(Constants.NATIVE_DATA_PRIVATE_KEY); @@ -117,4 +123,11 @@ public static Object verifySha384withEcdsaSignature(BArray dataValue, BArray sig PublicKey key = (PublicKey) publicKey.getNativeData(Constants.NATIVE_DATA_PUBLIC_KEY); return CryptoUtils.verify("SHA384withECDSA", key, data, signature); } + + public static Object verifySha256withEcdsaSignature(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("SHA256withECDSA", key, data, signature); + } } From 33a0979f0737de1a9d09919a02fa1e3dc9039b64 Mon Sep 17 00:00:00 2001 From: bhashinee Date: Mon, 18 Dec 2023 11:58:15 +0530 Subject: [PATCH 4/4] Update the changelog --- changelog.md | 5 ++++- docs/spec/spec.md | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index f6d4dd67..739572a9 100644 --- a/changelog.md +++ b/changelog.md @@ -5,7 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] -## [2.6.1] - 2023-12-08 +### Added +- [Introduce new APIs to sign and verify using SHA256withECDSA](https://github.com/ballerina-platform/ballerina-library/issues/5889) + +## [2.6.1] - 2023-12-12 ### Added - [Introduce new APIs to decode private and public keys from files](https://github.com/ballerina-platform/ballerina-library/issues/5871) diff --git a/docs/spec/spec.md b/docs/spec/spec.md index 2f06b776..13d51cbe 100644 --- a/docs/spec/spec.md +++ b/docs/spec/spec.md @@ -60,6 +60,7 @@ The conforming implementation of the specification is released and included in t * 6.1.4. [RSA-SHA384](#614-rsa-sha384) * 6.1.5. [RSA-SHA512](#615-rsa-sha512) * 6.1.6. [SHA384withECDSA](#616-sha384withecdsa) + * 6.1.7. [SHA256withECDSA](#617-sha256withecdsa) * 6.2. [Verify signature](#62-verify-signature) * 6.2.1. [RSA-MD5](#621-rsa-md5) * 6.2.2. [RSA-SHA1](#622-rsa-sha1) @@ -67,6 +68,7 @@ The conforming implementation of the specification is released and included in t * 6.2.4. [RSA-SHA384](#624-rsa-sha384) * 6.2.5. [RSA-SHA512](#625-rsa-sha512) * 6.2.6. [SHA384withECDSA](#626-sha384withecdsa) + * 6.2.7. [SHA256withECDSA](#627-sha256withecdsa) ## 1. [Overview](#1-overview) @@ -534,6 +536,21 @@ crypto:PrivateKey privateKey = check crypto:decodeEcPrivateKeyFromKeyStore(keySt byte[] signature = check crypto:signSha384withEcdsa(data, privateKey); ``` +#### 6.1.7. [SHA256withECDSA](#617-sha256withecdsa) + +This API can be used to create the SHA256withECDSA 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:signSha256withEcdsa(data, privateKey); +``` + ### 6.2. [Verify signature](#62-verify-signature) #### 6.2.1. [RSA-MD5](#621-rsa-md5) @@ -637,3 +654,20 @@ byte[] signature = check crypto:signSha384withEcdsa(data, privateKey); crypto:PublicKey publicKey = check crypto:decodeEcPublicKeyFromTrustStore(keyStore, "keyAlias"); boolean validity = check crypto:verifySha384withEcdsaSignature(data, signature, publicKey); ``` + +#### 6.2.7. [SHA256withECDSA](#627-sha256withecdsa) + +This API can be used to verify the SHA256withECDSA 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:signSha256withEcdsa(data, privateKey); +crypto:PublicKey publicKey = check crypto:decodeEcPublicKeyFromTrustStore(keyStore, "keyAlias"); +boolean validity = check crypto:verifySha256withEcdsaSignature(data, signature, publicKey); +```