Subtle Crypto
The Subtle Crypto Interface provides an advanced way to manage cryptographic operations such as encryption, decryption, signing, signature verifications, key wrapping/unwrapping, key import/export, etc. The Key lifecycle management should be done by the developers. The Subtle Crypto interface offers more algoritm and cryptographic mode as well as configuration.
Generating Keys
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
Crypto.Subtle | generateKey | algorithm: T, extractable: boolean, usages: string[] | Result<CryptoKey, Error> | Generate a CryptoKey based on the algorithm object and usages provided. Return a ResultSet Result<CryptoKey, Error> containing either the generated CryptoKey or an Error . |
A CryptoKey
contains the key type and usages and is an handle on the key.
class CryptoKey extends Key
{
algorithm!: string;
extractable!: boolean;
usages!: string[];
}
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
crypto::subtle | generate_key | algorithm: GenAlgorithm, extractable: bool, usages: &[&str] | Result<CryptoKey, Error> | Generate a CryptoKey based on the algorithm object and usages provided. Return a ResultSet Result<CryptoKey, Error> containing either the generated CryptoKey or an Error . |
A CryptoKey
contains the key type, usages and is an handle on the key.
pub struct CryptoKey {
id: String,
alias: Option<String>,
key_type: String,
extractable: bool,
family: String,
usages: Vec<String>,
algorithm: String
}
Depending on the type of key that needs to be generated a GenAlgorithm
Enum variants
is passed as parameters.
pub enum KeyGenAlgorithm {
Rsa(RsaHashedKeyGenParams),
Ecc(EcKeyGenParams),
Aes(AesKeyGenParams),
Hmac(HmacKeyGenParams),
}
RSA Key
For generating RSA key, the algorithm object to use is Crypto.RsaHashedKeyGenParams
.
When generating an RSA Key, only the private key is generated and not a key pair. Usages needs to be align with that, for instance an RSA private key can only be used for signing, decrypting or unwraping.
class RsaHashedKeyGenParams {
modulusLength: u32 = 2048; // 2048, 3072, 4096
publicExponent: u32 = 65537;
hash: string = 'SHA2-256'; // "SHA2-256", "SHA2-384", "SHA2-512"
}
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function subtleCryptoRSA(): void
{
// Generate RSA key
let rsaKey = Crypto.Subtle.generateKey({modulusLength: 2048, publicExponent: 65537, hash: "SHA2-256"} as Crypto.RsaHashedKeyGenParams, true, ["decrypt", "sign"]);
}
Public key derivation can be done directly from the private key and will automatically get the usages aligned with the private one.
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
Crypto.Subtle | getPublicKey | key: CryptoKey | Result<CryptoKey, Error> | Derive the public CryptoKey corresponding to the private key provided. Return a ResultSet Result<CryptoKey, Error> containing either the generated CryptoKey or an Error . |
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function subtleCryptoRSA(): void
{
// Generate RSA key
let rsaKeyResult = Crypto.Subtle.generateKey({modulusLength: 2048, publicExponent: 65537, hash: "SHA2-256"} as Crypto.RsaHashedKeyGenParams, true, ["decrypt", "sign"]);
let rsaKey = rsaKeyResult.data as Crypto.CryptoKey;
// Derive RSA public key
let publicRsaKeyResult = Crypto.Subtle.getPublicKey(rsaKey);
}
For generating RSA key, the algorithm object to use is RsaHashedKeyGenParams
.
When generating an RSA Key, only the private key is generated and not a key pair. Usages needs to be align with that, for instance an RSA private key can only be used for signing, decrypting or unwraping.
pub struct RsaHashedKeyGenParams {
pub modulus_length: u32, // 2048, 3072, 4096
pub public_exponent: u32, // 65537
pub hash: String // "SHA2-256", "SHA2-384", "SHA2-512"
}
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_rsa(input: String) {
let rsa_params = subtle::RsaHashedKeyGenParams {
modulus_length: 2048,
public_exponent: 65537,
hash: "SHA2-256"
};
let key_usages_slice: Vec<&str> = vec!["decrypt", "sign"];
let gen_algorithm = subtle::KeyGenAlgorithm::Rsa(rsa_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
}
Public key derivation can be done directly from the private key and will automatically get the usages aligned with the private one.
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
crypto::subtle | get_public_key | key: CryptoKey | Result<CryptoKey, Error> | Derive the public CryptoKey corresponding to the private key provided. Return a ResultSet Result<CryptoKey, Error> containing either the generated CryptoKey or an Error . |
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_rsa(input: String) {
let rsa_params = subtle::RsaHashedKeyGenParams {
modulus_length: 2048,
public_exponent: 65537,
hash: "SHA2-256"
};
let key_usages_slice: Vec<&str> = vec!["decrypt", "sign"];
let gen_algorithm = subtle::KeyGenAlgorithm::Rsa(rsa_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
let public_crypto_key: CryptoKey = match subtle::get_public_key(&crypto_key) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
}
EC Key
For generating EC key, the algorithm object to use is Crypto.EcKeyGenParams
.
When generating an EC Key, only the private key is generated and not a key pair. Usages needs to be align with that, for instance an EC private key can only be used for signing or for derivation.
export class EcKeyGenParams {
namedCurve: string = 'P-256'; // "P-256", "P-384", "P-521"
}
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function subtleCryptoEC(): void
{
// Generate EC key
let eccKey = Crypto.Subtle.generateKey({namedCurve: "P-256"} as Crypto.EcKeyGenParams, true, ["sign"]);
}
Public key derivation can be done directly from the private key and will automatically get the usages aligned with the private one.
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
Crypto.Subtle | getPublicKey | key: CryptoKey | Result<CryptoKey, Error> | Derive the public CryptoKey corresponding to the private key provided. Return a ResultSet Result<CryptoKey, Error> containing either the generated CryptoKey or an Error . |
/**
* @query
*/
export function subtleCryptoEC(): void
{
// Generate EC key
let eccKey = Crypto.Subtle.generateKey({namedCurve: "P-256"} as Crypto.EcKeyGenParams, true, ["sign"]);
// Derive Public key
let public_eccKey = Crypto.Subtle.getPublicKey(eccKey);
}
For generating EC key, the algorithm object to use is EcKeyGenParams
.
When generating an EC Key, only the private key is generated and not a key pair. Usages needs to be align with that, for instance an EC private key can only be used for signing or for derivation.
pub struct EcKeyGenParams {
pub named_curve: String // "P-256", "P-384", "P-521"
}
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_ec(input: String) {
let ec_params = subtle::EcKeyGenParams { named_curve: "P-256" };
let key_usages_slice: Vec<&str> = vec!["sign"];
let gen_algorithm = subtle::KeyGenAlgorithm::Ecc(ec_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
}
Public key derivation can be done directly from the private key and will automatically get the usages aligned with the private one.
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
crypto::subtle | get_public_key | key: CryptoKey | Result<CryptoKey, Error> | Derive the public CryptoKey corresponding to the private key provided. Return a ResultSet Result<CryptoKey, Error> containing either the generated CryptoKey or an Error . |
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_ec(input: String) {
let ec_params = subtle::EcKeyGenParams { named_curve: "P-256" };
let key_usages_slice: Vec<&str> = vec!["sign"];
let gen_algorithm = subtle::KeyGenAlgorithm::Ecc(ec_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
let public_key: CryptoKey = match subtle::get_public_key(&crypto_key) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
}
AES Key
For generating AES key, the algorithm object to use is Crypto.AesKeyGenParams
.
class AesKeyGenParams {
length: u32 = 256; // 128, 192, 256
}
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function subtleCryptoAES(): void
{
// Generate AES key
let aesKey = Crypto.Subtle.generateKey({length: 256} as Crypto.AesKeyGenParams, true, ["encrypt", "decrypt"]);
}
For generating AES key, the algorithm object to use is AesKeyGenParams
.
pub struct AesKeyGenParams {
pub length: u32 // 128, 192, 256
}
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_aes(input: String) {
let aes_params = subtle::AesKeyGenParams { length: 256 };
let key_usages_slice: Vec<&str> = vec!["encrypt", "decrypt"];
let gen_algorithm = subtle::KeyGenAlgorithm::Aes(aes_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
}
HMAC Key
For generating HMAC key, the algorithm object to use is Crypto.HmacKeyGenParams
.
export class HmacKeyGenParams {
hash: string = 'SHA2-256'; //SHA2-384, SHA2-512
}
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function subtleCryptoHMAC(): void
{
// Generate HMAC key
let hmacKey = Crypto.Subtle.generateKey({hash: 'SHA2-256'} as Crypto.HmacKeyGenParams, true, ["sign", "verify"]);
}
For generating HMAC key, the algorithm object to use is HmacKeyGenParams
.
pub struct HmacKeyGenParams {
pub hash: String, //"SHA2-256", "SHA2-384", "SHA2-512"
}
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_hmac(input: String) {
let hmac_params = subtle::HmacKeyGenParams { hash: "SHA2-256".to_string() };
let key_usages_slice: Vec<&str> = vec!["sign", "verify"];
let gen_algorithm = subtle::KeyGenAlgorithm::Hmac(hmac_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
}
Data encryption and decryption
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
Crypto.Subtle | encrypt | algorithm: T, key: CryptoKey, clearText: ArrayBuffer | Result<ArrayBuffer, Error> | Encrypt the clearText with the algorithm object and key provided. Return an ArrayBuffer containing the cipherText or an Error . |
Crypto.Subtle | decrypt | algorithm: T, key: CryptoKey, cipherText: ArrayBuffer | Result<ArrayBuffer, Error> | Decrypt the cipherText with the algorithm object and key provided. Return an ArrayBuffer containing the clearText or an Error . |
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
crypto::subtle | encrypt | algorithm: EncryptAlgorithm, key: CryptoKey, clearText: [u8] | Result<Vec<u8>, Error> | Encrypt the clearText with the algorithm object and key provided. Return an ArrayBuffer containing the cipherText or an Error . |
crypto::subtle | decrypt | algorithm: EncryptAlgorithm, key: CryptoKey, cipherText: [u8] | Result<Vec<u8>, Error> | Decrypt the cipherText with the algorithm object and key provided. Return an ArrayBuffer containing the clearText or an Error . |
Depending on the type of encryption that needs to be done an EncryptAlgorithm
Enum variants
is passed as parameters.
pub enum EncryptAlgorithm {
RsaOaep(RsaOaepParams),
AesGcm(AesGcmParams),
}
AES-GCM
For encrypting with AES-GCM you need an AES key and to use the Crypto.AesGcmParams
algorithm object.
class AesGcmParams {
iv!: ArrayBuffer; // iv cannot be empty
additionalData: ArrayBuffer = new ArrayBuffer(0);
tagLength: u32 = 128;
}
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function subtleCryptoAESGCM(): void
{
// Generate AES key
let aesKeyResult = Crypto.Subtle.generateKey({length: 256} as Crypto.AesKeyGenParams, true, ["encrypt", "decrypt"]);
let aesKey = aesKeyResult.data as Crypto.CryptoKey;
// Generate iv
let iv = Crypto.getRandomValues(12);
let aesGcmParams = {iv : iv.buffer, additionalData : new ArrayBuffer(0), tagLength : 128} as Crypto.AesGcmParams;
let cipher = Crypto.Subtle.encrypt(aesGcmParams, aesKey, String.UTF8.encode("Hello World"));
let clearText = Crypto.Subtle.decrypt(aesGcmParams, aesKey, cipher.data as ArrayBuffer);
}
For encrypting with AES-GCM you need an AES key and to use the Crypto.AesGcmParams
algorithm object.
pub struct AesGcmParams {
pub iv: Vec<u8>, // iv cannot be empty
pub additional_data: Vec<u8>,
pub tag_length: u32
}
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_aes_gcm(input: String) {
// Generate AES key
let aes_params = subtle::AesKeyGenParams { length: 256 };
let key_usages_slice: Vec<&str> = vec!["encrypt", "decrypt"];
let gen_algorithm = subtle::KeyGenAlgorithm::Aes(aes_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Generate IV
let random_bytes = match klave::crypto::random::get_random_bytes(12) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
//Generate GCM parameters
let aes_params = subtle::AesGcmParams {
iv: &random_bytes,
additionalData: vec![],
tagLength: 128
};
let crypt_algorithm = subtle::EncryptAlgorithm::AesGcm(aes_params);
// Encrypt
let encrypted_text = match subtle::encrypt(&crypt_algorithm, &crypto_key, &String::from("Hello World").into_bytes()) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Decrypt
let decrypted_text = match subtle::decrypt(&crypt_algorithm, &crypto_key, &encrypted_text) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
}
RSA-OAEP
For encrypting with RSA-OAEP you need an RSA key and to use the Crypto.RsaOaepParams
algorithm object.
export class RsaOaepParams {
label: ArrayBuffer = new ArrayBuffer(0);
}
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function subtleCryptoRSAOAEP(): void
{
// Generate RSA key
let rsakeyResult = Crypto.Subtle.generateKey({modulusLength: 2048, publicExponent: 65537, hash: "SHA2-256"} as Crypto.RsaHashedKeyGenParams, true, ["encrypt", "decrypt"]);
let rsaKey = rsakeyResult.data as Crypto.CryptoKey;
// Encrypt and Decrypt
let rsaOaepParams = {label : new ArrayBuffer(0)} as Crypto.RsaOaepParams;
let cipher = Crypto.Subtle.encrypt(rsaOaepParams, rsaKey, String.UTF8.encode("Hello World"));
let clearText = Crypto.Subtle.decrypt(rsaOaepParams, rsaKey, cipher.data as ArrayBuffer);
}
For encrypting with RSA-OAEP you need an RSA key and to use the RsaOaepParams
algorithm object.
pub struct RsaOaepParams {
pub label: Vec<u8>
}
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_rsa_oaep(input: String) {
// Generate RSA key
let rsa_params = subtle::RsaHashedKeyGenParams {
modulus_length: 2048,
public_exponent: 65537,
hash: "SHA2-256"
};
let key_usages_slice: Vec<&str> = vec!["encrypt", "decrypt"];
let gen_algorithm = subtle::KeyGenAlgorithm::Rsa(rsa_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Encrypt
let rsa_oaep_params = subtle::RsaOaepParams { label: vec![] };
let crypt_algorithm = subtle::EncryptAlgorithm::RsaOaep(rsa_oaep_params);
let encrypted_text = match subtle::encrypt(&crypt_algorithm, &crypto_key, &String::from("Hello World").into_bytes()) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Decrypt
let decrypted_text = match subtle::decrypt(&crypt_algorithm, &crypto_key, &encrypted_text) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
}
Signing and Verifying
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
Crypto.Subtle | sign | algorithm: T, key: CryptoKey, data: ArrayBuffer | Result<ArrayBuffer, Error> | Sign the data with the algorithm object and key provided. Return an ArrayBuffer containing the signature or an Error . |
Crypto.Subtle | verify | algorithm: T, key: CryptoKey, data: ArrayBuffer, signature: ArrayBuffer | Result<Crypto.SignatureVerification, Error> | Verify the signature against the data with the algorithm object and key provided. Return an Crypto.SignatureVerification containing a boolean or an Error . |
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
crypto::subtle | sign | algorithm: SignAlgorithm, key: CryptoKey, data: [u8] | Result<Vec<u8>, Error> | Sign the data with the algorithm object and key provided. Return an Vec<u8> containing the signature or an Error . |
crypto::subtle | verify | algorithm: SignAlgorithm, key: CryptoKey, data: [u8], signature: [u8] | Result<VerifySignResult, Error> | Verify the signature against the data with the algorithm object and key provided. Return an VerifySignResult containing a bool or an Error . |
Depending on the type of signature that needs to be done a SignAlgorithm
Enum variants
is passed as parameters.
pub enum SignAlgorithm {
Ecdsa(EcdsaParams),
RsaPss(RsaPssParams),
Hmac(HmacParams),
}
ECDSA
For ECDSA signature you need an EC key pair and to use the Crypto.EcdsaParams
algorithm object.
export class EcdsaParams {
hash: string = 'SHA2-256'; // "SHA2-256", "SHA2-384", "SHA2-512"
}
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function subtleCryptoECDSA(): void
{
// Generate EC key
let eccKeyResult = Crypto.Subtle.generateKey({namedCurve: "P-256"} as Crypto.EcKeyGenParams, true, ["sign", "verify"]);
let eccKey = eccKeyResult.data as Crypto.CryptoKey;
// Sign and Verify
let ecdsaParams = {hash: "SHA2-256"} as Crypto.EcdsaParams;
let signEcc = Crypto.Subtle.sign(ecdsaParams, eccKey, String.UTF8.encode("Hello World"));
let verifyEcc = Crypto.Subtle.verify(ecdsaParams, eccKey, String.UTF8.encode("Hello World"), signEcc.data as ArrayBuffer);
let verification = verifyEcc.data as SignatureVerification;
// Validate signature : if(verification.isValid) ...
}
For ECDSA signature you need an EC key pair and to use the EcdsaParams
algorithm object.
pub struct EcdsaParams {
pub hash: String // "SHA2-256", "SHA2-384", "SHA2-512"
}
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_ecdsa(input: String) {
// Generate Key
let ec_params = subtle::EcKeyGenParams { named_curve: "P-256" };
let key_usages_slice: Vec<&str> = vec!["sign", "verify"];
let gen_algorithm = subtle::KeyGenAlgorithm::Ecc(ec_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Sign
let sign_ec_params = subtle::EcdsaParams { hash: "SHA2-256" };
let sign_algorithm = subtle::SignAlgorithm::Ecdsa(sign_ec_params);
let signature = match subtle::sign(&sign_algorithm, &crypto_key, &String::from("Hello World").into_bytes()) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Verify
let verify_result = match subtle::verify(&sign_algorithm, &crypto_key, &String::from("Hello World").into_bytes(), &signature) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
if verify_result.is_valid() {
klave::notifier::send_string("Verified");
}
else {
klave::notifier::send_string("Not Verified");
}
}
RSA-PSS
For RSA-PSS signature you need an RSA key pair and to use the Crypto.RsaPssParams
algorithm object.
export class RsaPssParams {
saltLength: u32 = 0;
}
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function subtleCryptoRSAPSS(): void
{
// Generate RSA key
let rsaKeyResult = Crypto.Subtle.generateKey({modulusLength: 2048, publicExponent: 65537, hash: "SHA2-256"} as Crypto.RsaHashedKeyGenParams, true, ["sign", "verify"]);
let rsaKey = rsaKeyResult.data as Crypto.CryptoKey;
// Sign and Verify
let rsaPssParams = {saltLength: 32} as Crypto.RsaPssParams;
let signRsa = Crypto.Subtle.sign(rsaPssParams, rsaKey, String.UTF8.encode("Hello World"));
let verifyRsa = Crypto.Subtle.verify(rsaPssParams, rsaKey, String.UTF8.encode("Hello World"), signRsa.data as ArrayBuffer);
let verification = verifyRsa.data as SignatureVerification;
// Validate signature : if(verification.isValid) ...
}
For RSA-PSS signature you need an RSA key pair and to use the RsaPssParams
algorithm object.
pub struct RsaPssParams {
pub salt_length: u32
}
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_rsa_pss(input: String) {
// Generate RSA key
let rsa_params = subtle::RsaHashedKeyGenParams {
modulus_length: 2048,
public_exponent: 65537,
hash: "SHA2-256"
};
let key_usages_slice: Vec<&str> = vec!["sign", "verify"];
let gen_algorithm = subtle::KeyGenAlgorithm::Rsa(rsa_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Sign
let sign_rsa_params = subtle::RsaPssParams { salt_length: 0 };
let sign_algorithm = subtle::SignAlgorithm::RsaPss(sign_rsa_params);
let signature = match subtle::sign(&sign_algorithm, &crypto_key, &String::from("Hello World").into_bytes()) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Verify
let verify_result = match subtle::verify(&sign_algorithm, &crypto_key, &String::from("Hello World").into_bytes(), &signature) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
if verify_result.is_valid() {
klave::notifier::send_string("Verified");
}
else {
klave::notifier::send_string("Not Verified");
}
}
HMAC
For HMAC signature you need an HMAC key and to use the Crypto.HmacKeyGenParams
algorithm object.
export class HmacKeyGenParams {
hash: string = 'SHA2-256'; //SHA2-384, SHA2-512
}
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function subtleCryptoHMAC(): void
{
// Generate HMAC key
let hmacKeyResult = Crypto.Subtle.generateKey({hash: 'SHA2-256'} as Crypto.HmacKeyGenParams, true, ["sign", "verify"]);
let hmacKey = hmacKeyResult.data as Crypto.CryptoKey;
// Sign and Verify
let hmacParams = {hash: 'SHA2-256'} as Crypto.HmacKeyGenParams;
let signHmac = Crypto.Subtle.sign(hmacParams, hmacKey, String.UTF8.encode("Hello World"));
let verifyHmac = Crypto.Subtle.verify(hmacParams, hmacKey, String.UTF8.encode("Hello World"), signHmac.data as ArrayBuffer);
let verification = verifyHmac.data as SignatureVerification;
// Validate signature : if(verification.isValid) ...
}
For HMAC signature you need an HMAC key and to use the HmacParams
algorithm object.
pub struct HmacParams {
pub hash: String,
}
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_hmac(input: String) {
// Generate HMAC key
let hmac_params = subtle::HmacKeyGenParams { hash: "SHA2-256".to_string() };
let key_usages_slice: Vec<&str> = vec!["sign", "verify"];
let gen_algorithm = subtle::KeyGenAlgorithm::Hmac(hmac_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Sign
let sign_hmac_params = subtle::HmacParams { hash: "SHA2-256".to_string() };
let sign_algorithm = subtle::SignAlgorithm::Hmac(sign_hmac_params);
let signature = match subtle::sign(&sign_algorithm, &crypto_key, &String::from("Hello World").into_bytes()) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Verify
let verify_result = match subtle::verify(&sign_algorithm, &crypto_key, &String::from("Hello World").into_bytes(), &signature) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
if verify_result.is_valid() {
klave::notifier::send_string("Verified");
}
else {
klave::notifier::send_string("Not Verified");
}
}
Key wrapping
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
Crypto.Subtle | wrapKey | format: string, key: CryptoKey, wrappingKey: CryptoKey, wrapAlgo: T | Result<ArrayBuffer, Error> | Wrap the key in the format specified with the wrappingKey using the wrapping algorithm . Return an ArrayBuffer containing the wrapped key or an Error . |
Crypto.Subtle | unwrapKey | format: string, wrappedKey: ArrayBuffer, unwrappingKey: CryptoKey, unwrapAlgo: T, unwrappedKeyAlgo: E, extractable: boolean, usages: string[] | Result<CryptoKey, Error> | Unwrap the wrappedKey wrapped in the format with the unwrappingKey and unwrapAlgo and create a Cryptokey with the specified unwrappedKeyAlgo and parameters. Return a result set containing a Crypto.CryptoKey or an Error . |
Format that can be used depending on the key you want to wrap/unwrap are the following: raw
, spki
, pkcs8
, pkcs1
, sec1
.
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
crypto::subtle | wrap_key | format: string, key: CryptoKey, wrapping_key: CryptoKey, algorithm: WrapAlgorithm | Result<Vec<u8>, Error> | Wrap the key in the format specified with the wrapping_key using the wrapping algorithm . Return an Vec<u8> containing the wrapped key or an Error . |
crypto::subtle | unwrap_key | format: string, wrappedKey: [u8], unwrapping_key: CryptoKey, unwrap_algorithm: WrapAlgorithm, unwrapped_key_algorithm: GenAlgorithm, extractable: bool, usages: [&str] | Result<CryptoKey, Error> | Unwrap the wrapped_key wrapped in the format with the unwrapping_key and unwrap_algorithm and create a Cryptokey with the specified unwrapped_key_algorithm and parameters. Return a result set containing a CryptoKey or an Error . |
Depending on the type of wrapping that needs to be done a WrapAlgorithm
Enum variants
is passed as parameters.
pub enum KeyWrapAlgorithm {
RsaOaep(RsaOaepParams),
AesGcm(AesGcmParams),
AesKw,
}
Format that can be used depending on the key you want to wrap/unwrap are the following: raw
, spki
, pkcs8
, pkcs1
, sec1
.
AES-KW
To wrap and unwrap key with AES-KW you will need an AES key, a key to wrap and to use NamedAlgorithm
.
export class NamedAlgorithm {
name!: string;
}
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function subtleCryptoAESKW(): void
{
// Generate wrapping AES key
let aesKeyResult = Crypto.Subtle.generateKey({length: 256} as Crypto.AesKeyGenParams, true, ["wrap_key", "unwrap_key"]);
let aesKey = aesKeyResult.data as Crypto.CryptoKey;
// Generate AES key to wrap
let aesKeyToWrapResult = Crypto.Subtle.generateKey({length: 256} as Crypto.AesKeyGenParams, true, ["encrypt", "decrypt"]);
let aesKeyToWrap = aesKeyToWrapResult.data as Crypto.CryptoKey;
// Wrap and Unwrap
let aesKwParams = {name: "AES-KW"} as Crypto.NamedAlgorithm;
let wrappedKeyResult = Crypto.Subtle.wrapKey("raw", aesKeyToWrap, aesKey, aesKwParams);
let unwrappedKeyResult = Crypto.Subtle.unwrapKey("raw", wrappedKeyResult.data, aesKey, aesKwParams, {length: 256} as Crypto.AesKeyGenParams, true, ["encrypt", "decrypt"]);
}
To wrap and unwrap key with AES-KW you will need an AES key and a key to wrap .
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_aes_kw(input: String) {
// Generate wrapping AES key
let aes_params_wrap_key = subtle::AesKeyGenParams { length: 256 };
let key_usages_wrap_key: Vec<&str> = vec!["wrap_key", "unwrap_key"];
let gen_algorithm_wrap_key = subtle::KeyGenAlgorithm::Aes(aes_params_wrap_key);
let wrapping_key: CryptoKey = match subtle::generate_key(&gen_algorithm_wrap_key, true, &key_usages_wrap_key) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Generate AES key to wrap
let aes_params = subtle::AesKeyGenParams { length: 256 };
let key_usages_slice: Vec<&str> = vec!["encrypt", "decrypt"];
let gen_algorithm = subtle::KeyGenAlgorithm::Aes(aes_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Wrap
let kw_wrap_algo = subtle::KeyWrapAlgorithm::AesKw;
let wrapped_key = match subtle::wrap_key(&"raw", &crypto_key, &wrapping_key, &kw_wrap_algo) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Unwrap
let unwrapped_key = match subtle::unwrap_key(&"raw", &wrapped_key, &wrapping_key,
&kw_wrap_algo,
&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
}
AES-GCM
To wrap and unwrap key with AES-GCM you will need an AES key, a key to wrap and to use Crypto.AesGcmParams
algorithm object.
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function subtleCryptoAESGCM(): void
{
// Generate wrapping AES key
let aesKeyResult = Crypto.Subtle.generateKey({length: 256} as Crypto.AesKeyGenParams, true, ["wrap_key", "unwrap_key"]);
let aesKey = aesKeyResult.data as Crypto.CryptoKey;
// Generate AES key to wrap
let aesKeyToWrapResult = Crypto.Subtle.generateKey({length: 256} as Crypto.AesKeyGenParams, true, ["encrypt", "decrypt"]);
let aesKeyToWrap = aesKeyToWrapResult.data as Crypto.CryptoKey;
// Wrap and Unwrap
let iv = Crypto.getRandomValues(12);
let aesGcmParams = {iv : iv.buffer, additionalData : new ArrayBuffer(0), tagLength : 128} as Crypto.AesGcmParams;
let wrappedKeyResult = Crypto.Subtle.wrapKey("raw", aesKeyToWrap, aesKey, aesGcmParams);
let unwrappedKeyResult = Crypto.Subtle.unwrapKey("raw", wrappedKeyResult.data, aesKey, aesGcmParams, {length: 256} as Crypto.AesKeyGenParams, true, ["encrypt", "decrypt"]);
}
To wrap and unwrap key with AES-GCM you will need an AES key, a key to wrap and to use AesGcmParams
algorithm object.
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_aes_gcm_wrap(input: String) {
// Generate wrapping AES key
let aes_params_wrap_key = subtle::AesKeyGenParams { length: 256 };
let key_usages_wrap_key: Vec<&str> = vec!["wrap_key", "unwrap_key"];
let gen_algorithm_wrap_key = subtle::KeyGenAlgorithm::Aes(aes_params_wrap_key);
let wrapping_key: CryptoKey = match subtle::generate_key(&gen_algorithm_wrap_key, true, &key_usages_wrap_key) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Generate AES key to wrap
let aes_params = subtle::AesKeyGenParams { length: 256 };
let key_usages_slice: Vec<&str> = vec!["encrypt", "decrypt"];
let gen_algorithm = subtle::KeyGenAlgorithm::Aes(aes_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Generate IV
let random_bytes = match klave::crypto::random::get_random_bytes(12) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
//Generate GCM parameters
let aes_gcm_params = subtle::AesGcmParams {
iv: &random_bytes,
additionalData: vec![],
tagLength: 128
};
let wrapping_algorithm = subtle::KeyWrapAlgorithm::AesGcm(aes_params);
// Wrap
let wrapped_key = match subtle::wrap_key(&"raw", &crypto_key, &wrapping_key, &wrapping_algorithm) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Unwrap
let unwrapped_key = match subtle::unwrap_key(&"raw", &wrapped_key, &wrapping_key,
&wrapping_algorithm,
&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
}
RSA-OAEP
To wrap and unwrap key with RSA-OAEP you will need an RSA key, a key to wrap and to use Crypto.RsaOaepParams
algorithm object.
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function subtleCryptoRSAOAEP(): void
{
// Generate wrapping RSA key
let rsakeyResult = Crypto.Subtle.generateKey({modulusLength: 2048, publicExponent: 65537, hash: "SHA2-256"} as Crypto.RsaHashedKeyGenParams, true, ["wrap_key", "unwrap_key"]);
let rsaKey = rsakeyResult.data as Crypto.CryptoKey;
// Generate AES key to wrap
let aesKeyToWrapResult = Crypto.Subtle.generateKey({length: 256} as Crypto.AesKeyGenParams, true, ["encrypt", "decrypt"]);
let aesKeyToWrap = aesKeyToWrapResult.data as Crypto.CryptoKey;
// Wrap and Unwrap
let rsaOaepParams = {label : new ArrayBuffer(0)} as Crypto.RsaOaepParams;
let wrappedKeyResult = Crypto.Subtle.wrapKey("raw", aesKeyToWrap, rsaKey, rsaOaepParams);
let unwrappedKeyResult = Crypto.Subtle.unwrapKey("raw", wrappedKeyResult.data, rsaKey, rsaOaepParams, {length: 256} as Crypto.AesKeyGenParams, true, ["encrypt", "decrypt"]);
}
To wrap and unwrap key with RSA-OAEP you will need an RSA key, a key to wrap and to use RsaOaepParams
algorithm object.
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_rsa_oaep_wrap(input: String) {
// Generate wrapping RSA key
let rsa_params_wrap_key = subtle::RsaHashedKeyGenParams {
modulus_length: 2048,
public_exponent: 65537,
hash: "SHA2-256"
};
let key_usages_wrap_key: Vec<&str> = vec!["wrap_key", "unwrap_key"];
let gen_algorithm_wrap_key = subtle::KeyGenAlgorithm::Rsa(rsa_params_wrap_key);
let wrapping_key: CryptoKey = match subtle::generate_key(&gen_algorithm_wrap_key, true, &key_usages_wrap_key) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Generate AES key to wrap
let aes_params = subtle::AesKeyGenParams { length: 256 };
let key_usages_slice: Vec<&str> = vec!["encrypt", "decrypt"];
let gen_algorithm = subtle::KeyGenAlgorithm::Aes(aes_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
//Generate RSA-OAEP parameters
let rsa_oaep_params = subtle::RsaOaepParams { label: vec![] };
let wrapping_algorithm = subtle::KeyWrapAlgorithm::RsaOaep(rsa_oaep_params);
// Wrap
let wrapped_key = match subtle::wrap_key(&"raw", &crypto_key, &wrapping_key, &wrapping_algorithm) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Unwrap
let unwrapped_key = match subtle::unwrap_key(&"raw", &wrapped_key, &wrapping_key,
&wrapping_algorithm,
&gen_algorithm, true, &key_usages_slice) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
}
Importing and Exporting key
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
Crypto.Subtle | importKey | format: string, keyData: ArrayBuffer, algorithm: T, extractable: boolean, usages: string[] | Result<CryptoKey, Error> | Import a key from the keyData in the format specified. Return a result set containing the CryptoKey or an Error . |
Crypto.Subtle | exportKey | format: string, key: CryptoKey | Result<ArrayBuffer, Error> | Export the key in the specified format . Return a result set containing a ArrayBuffer of the exported key or an Error . |
Depending on the type of Key to export or import the format to use are the following: raw
, spki
, pkcs8
, pkcs1
, sec1
.
If the key is not extractable
then export will fail.
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function subtleCryptoExportImportKey(): void
{
// Generate AES key to export
let aesKeyResult = Crypto.Subtle.generateKey({length: 256} as Crypto.AesKeyGenParams, true, ["encrypt", "decrypt"]);
let aesKey = aesKeyResult.data as Crypto.CryptoKey;
// Export and Import
let aesKeyExport = Crypto.Subtle.exportKey("raw", aesKey);
let importedAesKey = Crypto.Subtle.importKey("raw", aesKeyExport.data, {length: 256} as Crypto.AesKeyGenParams, true, ["encrypt", "decrypt"]);
}
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
crypto::subtle | import_key | format: string, keyData: [u8], algorithm: GenAlgorithm, extractable: bool, usages: [&str] | Result<CryptoKey, Error> | Import a key from the keyData in the format specified. Return a result set containing the CryptoKey or an Error . |
crypto::subtle | export_key | format: string, key: CryptoKey | Result<Vec<u8>, Error> | Export the key in the specified format . Return a result set containing a Vec<u8> of the exported key or an Error . |
Depending on the type of Key to export or import the format to use are the following: raw
, spki
, pkcs8
, pkcs1
, sec1
.
If the key is not extractable
then export will fail.
use klave::{self, crypto::subtle, crypto::subtle::CryptoKey};
fn subtle_crypto_export_import_key(input: String) {
// Generate AES key
let aes_params = subtle::AesKeyGenParams { length: 256 };
let key_usages: Vec<&str> = vec!["encrypt", "decrypt"];
let gen_algorithm = subtle::KeyGenAlgorithm::Aes(aes_params);
let crypto_key: CryptoKey = match subtle::generate_key(&gen_algorithm, true, &key_usages) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Export the Key
let exported_key = match subtle::export_key("raw", &crypto_key) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
// Import the Key
let imported_key = match subtle::import_key("raw", &exported_key, &gen_algorithm, true, &key_usages) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
}
}
Making data digest
The interface can be accessed through the Crypto.SHA
keyword and is compatible with SHA2 and SHA3 digest.
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
Crypto.Subtle | digest | algorithm: string, data: ArrayBuffer | Result<ArrayBuffer, Error> | Generate a digest of the data based on the algorithm specified. Return a ResultSet Result<ArrayBuffer, Error> containing either the digest in an ArrayBuffer or an Error . |
import { Crypto } from '@klave/sdk';
/**
* @query
*/
export function CryptoSHA_Test(): void
{
let data = String.UTF8.encode("Hello World");
let sha256 = Crypto.Subtle.digest("SHA2-256", data);
let sha384 = Crypto.Subtle.digest("SHA2-384", data);
let sha512 = Crypto.Subtle.digest("SHA2-512", data);
let sha3_256 = Crypto.Subtle.digest("SHA3-256", data);
let sha3_384 = Crypto.Subtle.digest("SHA3-384", data);
let sha3_512 = Crypto.Subtle.digest("SHA3-512", data);
}
Class | Operation | Parameters: type | Returns | Behavior |
---|---|---|---|---|
crypto::subtle | digest | algorithm: string, data: [u8] | Result<Vec<u8>, Error> | Generate a digest of the data based on the algorithm specified. Return a ResultSet Result<Vec<u8>, Error> containing either the digest in an Vec<u8> or an Error . |
use klave::{self, crypto::subtle}
fn digest(input: String) {
// Digest : SHA2-256, SHA2-384, SHA2-512, SHA3-256, SHA3-384, SHA3-512
let digest = match sha::digest("SHA2-256", &String::from("Hello World").into_bytes()) {
Ok(result) => result,
Err(err) => {
klave::notifier::send_string(&err.to_string());
return;
}
};
}
Last updated on