-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #539 from hwupathum/pqc
Update CryptoAPI
- Loading branch information
Showing
32 changed files
with
2,522 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
// Copyright (c) 2024 WSO2 LLC. (https://www.wso2.com). | ||
// | ||
// WSO2 LLC. licenses this file to you under the Apache License, | ||
// Version 2.0 (the "License"); you may not use this file except | ||
// in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, | ||
// software distributed under the License is distributed on an | ||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
// KIND, either express or implied. See the License for the | ||
// specific language governing permissions and limitations | ||
// under the License. | ||
|
||
# Represent the supported symmetric key sizes for AES algorithm. | ||
public type AesKeySize 16|24|32; | ||
|
||
# Represents the encapsulated secret and the ciphertext used in Hybrid Public Key Encryption (HPKE). | ||
# | ||
# + encapsulatedSecret - The encapsulated secret | ||
# + cipherText - The encrypted data | ||
public type HybridEncryptionResult record {| | ||
byte[] encapsulatedSecret; | ||
byte[] cipherText; | ||
|}; | ||
|
||
# Returns the ML-KEM-768-AES-hybrid-encrypted 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:PublicKey publicKey = check crypto:decodeMlKem768PublicKeyFromTrustStore(keyStore, "keyAlias"); | ||
# crypto:HybridEncryptionResult encryptionResult = crypto:encryptMlKem768Hpke(data, publicKey); | ||
# ``` | ||
# + input - The content to be encrypted | ||
# + publicKey - Public key used for encryption | ||
# + symmetricKeySize - The length of the symmetric key (in bytes) | ||
# + return - Encrypted data or else a `crypto:Error` if an error occurs | ||
public isolated function encryptMlKem768Hpke(byte[] input, PublicKey publicKey, AesKeySize symmetricKeySize = 32) returns HybridEncryptionResult|Error { | ||
EncapsulationResult encapsulationResult = check encapsulateMlKem768(publicKey); | ||
byte[] sharedSecret = check hkdfSha256(encapsulationResult.sharedSecret, symmetricKeySize); | ||
byte[] encapsulatedSecret = encapsulationResult.encapsulatedSecret; | ||
byte[] ciphertext = check encryptAesEcb(input, sharedSecret); | ||
return { | ||
encapsulatedSecret: encapsulatedSecret, | ||
cipherText: ciphertext | ||
}; | ||
} | ||
|
||
# Returns the ML-KEM-768-AES-hybrid-encrypted value for the given encrypted data. | ||
# ```ballerina | ||
# string input = "Hello Ballerina"; | ||
# byte[] data = input.toBytes(); | ||
# crypto:KeyStore keyStore = { | ||
# path: "/path/to/keyStore.p12", | ||
# password: "keyStorePassword" | ||
# }; | ||
# crypto:PublicKey publicKey = check crypto:decodeMlKem768PublicKeyFromTrustStore(keyStore, "keyAlias"); | ||
# crypto:HybridEncryptionResult encryptionResult = crypto:encryptMlKem768Hpke(data, publicKey); | ||
# byte[] cipherText = encryptionResult.cipherText; | ||
# byte[] encapsulatedKey = encryptionResult.encapsulatedSecret; | ||
# crypto:PrivateKey privateKey = check crypto:decodeMlKem768PrivateKeyFromKeyStore(keyStore, "keyAlias"); | ||
# byte[] decryptedData = check crypto:decryptMlKem768Hpke(cipherText, encapsulatedKey, privateKey); | ||
# ``` | ||
# + input - The content to be decrypted | ||
# + encapsulatedKey - The encapsulated secret | ||
# + privateKey - The MlKem private key used for decryption | ||
# + symmetricKeySize - The length of the symmetric key (in bytes) | ||
# + return - Decrypted data or else a `crypto:Error` if error occurs | ||
public isolated function decryptMlKem768Hpke(byte[] input, byte[] encapsulatedKey, PrivateKey privateKey, AesKeySize symmetricKeySize = 32) returns byte[]|Error { | ||
byte[] key = check decapsulateMlKem768(encapsulatedKey, privateKey); | ||
key = check hkdfSha256(key, symmetricKeySize); | ||
return check decryptAesEcb(input, key); | ||
} | ||
|
||
# Returns the RSA-KEM-ML-KEM-768-AES-hybrid-encrypted value for the given data. | ||
# ```ballerina | ||
# string input = "Hello Ballerina"; | ||
# byte[] data = input.toBytes(); | ||
# crypto:KeyStore mlkemKeyStore = { | ||
# path: "/path/to/mlkem/keyStore.p12", | ||
# password: "keyStorePassword" | ||
# }; | ||
# crypto:KeyStore rsaKeyStore = { | ||
# path: "/path/to/rsa/keyStore.p12", | ||
# password: "keyStorePassword" | ||
# }; | ||
# crypto:PublicKey mlkemPublicKey = check crypto:decodeMlKem768PublicKeyFromTrustStore(mlkemKeyStore, "keyAlias"); | ||
# crypto:PublicKey rsaPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(rsaKeyStore, "keyAlias"); | ||
# crypto:HybridEncryptionResult encryptionResult = crypto:encryptRsaKemMlKem768Hpke(data, rsaPublicKey, mlkemPublicKey); | ||
# ``` | ||
# + input - The content to be encrypted | ||
# + rsaPublicKey - The RSA public key used for encryption | ||
# + mlkemPublicKey - The MlKem public key used for encryption | ||
# + symmetricKeySize - The length of the symmetric key (in bytes) | ||
# + return - Encrypted data or else a `crypto:Error` if an error occurs | ||
public isolated function encryptRsaKemMlKem768Hpke(byte[] input, PublicKey rsaPublicKey, PublicKey mlkemPublicKey, AesKeySize symmetricKeySize = 32) returns HybridEncryptionResult|Error { | ||
EncapsulationResult hybridEncapsulationResult = check encapsulateRsaKemMlKem768(rsaPublicKey, mlkemPublicKey); | ||
byte[] sharedSecret = check hkdfSha256(hybridEncapsulationResult.sharedSecret, symmetricKeySize); | ||
byte[] ciphertext = check encryptAesEcb(input, sharedSecret); | ||
return { | ||
encapsulatedSecret: hybridEncapsulationResult.encapsulatedSecret, | ||
cipherText: ciphertext | ||
}; | ||
} | ||
|
||
# Returns the RSA-KEM-ML-KEM-768-AES-hybrid-encrypted value for the given encrypted data. | ||
# ```ballerina | ||
# string input = "Hello Ballerina"; | ||
# byte[] data = input.toBytes(); | ||
# crypto:KeyStore mlkemKeyStore = { | ||
# path: "/path/to/mlkem/keyStore.p12", | ||
# password: "keyStorePassword" | ||
# }; | ||
# crypto:KeyStore rsaKeyStore = { | ||
# path: "/path/to/rsa/keyStore.p12", | ||
# password: "keyStorePassword" | ||
# }; | ||
# crypto:PublicKey mlkemPublicKey = check crypto:decodeMlKem768PublicKeyFromTrustStore(mlkemKeyStore, "keyAlias"); | ||
# crypto:PublicKey rsaPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(rsaKeyStore, "keyAlias"); | ||
# crypto:HybridEncryptionResult encryptionResult = crypto:encryptRsaKemMlKem768Hpke(data, rsaPublicKey, mlkemPublicKey); | ||
# byte[] cipherText = encryptionResult.cipherText; | ||
# byte[] encapsulatedKey = encryptionResult.encapsulatedSecret; | ||
# crypto:PrivateKey mlkemPrivateKey = check crypto:decodeMlKem768PrivateKeyFromKeyStore(mlkemKeyStore, "keyAlias"); | ||
# crypto:PrivateKey rsaPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(rsaKeyStore, "keyAlias"); | ||
# byte[] decryptedData = check crypto:decryptRsaKemMlKem768Hpke(cipherText, encapsulatedKey, rsaPrivateKey, mlkemPrivateKey); | ||
# ``` | ||
# + input - The content to be decrypted | ||
# + encapsulatedKey - The encapsulated secret | ||
# + rsaPrivateKey - The RSA private key used for decryption | ||
# + mlkemPrivateKey - The MlKem private key used for decryption | ||
# + symmetricKeySize - The length of the symmetric key (in bytes) | ||
# + return - Decrypted data or else a `crypto:Error` if error occurs | ||
public isolated function decryptRsaKemMlKem768Hpke(byte[] input, byte[] encapsulatedKey, PrivateKey rsaPrivateKey, PrivateKey mlkemPrivateKey, AesKeySize symmetricKeySize = 32) returns byte[]|Error { | ||
byte[] key = check decapsulateRsaKemMlKem768(encapsulatedKey, rsaPrivateKey, mlkemPrivateKey); | ||
key = check hkdfSha256(key, symmetricKeySize); | ||
return check decryptAesEcb(input, key); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Copyright (c) 2024 WSO2 LLC. (https://www.wso2.com). | ||
// | ||
// WSO2 LLC. licenses this file to you under the Apache License, | ||
// Version 2.0 (the "License"); you may not use this file except | ||
// in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, | ||
// software distributed under the License is distributed on an | ||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
// KIND, either express or implied. See the License for the | ||
// specific language governing permissions and limitations | ||
// under the License. | ||
|
||
import ballerina/jballerina.java; | ||
|
||
# Returns HKDF (HMAC-based Key Derivation Function) using SHA-256 as the hash function. | ||
# ```ballerina | ||
# string secret = "some-secret"; | ||
# byte[] key = secret.toBytes(); | ||
# byte[] hash = crypto:hkdfSha256(key, 32); | ||
# ``` | ||
# + input - The input key material to derive the key from | ||
# + length - The length of the output keying material (OKM) in bytes | ||
# + salt - Optional salt value, a non-secret random value | ||
# + info - Optional context and application-specific information | ||
# + return - The derived keying material (OKM) of the specified length | ||
public isolated function hkdfSha256(byte[] input, int length, byte[] salt = [], byte[] info = []) returns byte[]|Error = @java:Method { | ||
name: "hkdfSha256", | ||
'class: "io.ballerina.stdlib.crypto.nativeimpl.Kdf" | ||
} external; |
Oops, something went wrong.