Skip to content
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

Introduce new APIs to sign and verify using SHA256withECDSA #537

Merged
merged 5 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions ballerina/sign_verify.bal
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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;
13 changes: 13 additions & 0 deletions ballerina/tests/sign_verify_test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
5 changes: 5 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### 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)

Expand Down
34 changes: 34 additions & 0 deletions docs/spec/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,15 @@ 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)
* 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)
* 6.2.7. [SHA256withECDSA](#627-sha256withecdsa)

## 1. [Overview](#1-overview)

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
```
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}
Loading