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.
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[];}
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 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);}
Verify the signature against the data with the algorithm object and key provided. Return an Crypto.SignatureVerification containing a boolean or an Error.
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) ...}
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.
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-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"]);}
Import a key from the keyDatain 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"]);}
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);}