This document describes the Crypto library available in the JavaScript environment for app serivices.
Object | Crypto |
Functions |
hash hmac cipher ecdh |
Object |
Hash |
Functions |
update final |
Object |
Hmac |
Functions |
update final |
Object |
Cipher |
Members |
iv getIv crypt close |
Object |
Ecdh |
Members |
public secret close |
Examples |
Encrypting and signing a JS object |
Creates a Hash object that can be used for the calculation of cryptographic hashes.
The objects allocates persistent memory in the JavaScript Runtime until the final function is called.
string algorithm | The hash algorithm to be used. Supported values are "SHA224", "SHA256", "SHA384", "SHA512", "SHA512_224", "SHA512_256", "SHA1", "MD5", "MD4". |
Hash | An object that can be used for the hash calculation. |
var digest = Crypto.hash("SHA256").update("data1").update("data2").final();
Creates a Hmac object that can be used for the calculation of a hash-based message authentication code.
The objects allocates persistent memory in the JavaScript Runtime until the final function is called.
string algorithm | The hash algorithm to be used. Supported values are "SHA224", "SHA256", "SHA384", "SHA512", "SHA512_224", "SHA512_256", "SHA1", "MD5", "MD4". |
string/Uint8Array key | The password or key that shall be used for the calculation. |
Hmac | An object that can be used for the HMAC calculation. |
var mac = Crypto.hmac("SHA256","password").update("data1").update("data2").final();
Creates a Cipher object that can be used for the encryption / decryption.
The objects allocates persistent memory in the JavaScript Runtime until close or crypt with last=true is called.
Note: Cryptography is non-trivial. It's easy to make small mistakes on application level that break security completely. Don't just use the library functions but make sure you have a good understanding how to use the specific algorithm and mode.
string algorithm | The cryptographic algorithm to be used. Supported values are "AES", "RC4", "DES". |
string mode | The mode of operation to be used. Supported modes for "AES" are "ECB", "CTR", "CBC", "CTS", "CFB". null defaults to "ECB". Supported modes for "DES" are "CBC". Use null for "RC4". |
string/Uint8Array key |
The key for encryption/decryption. For "AES" a key of 16 bytes (AES-128), 24 bytes (AES-192) or 32 bytes (AES-256) is needed. The function accepts both hexstrings and binary keys given as a Uint8Array. For "DES" a key of 8 bytes (64 bit) is needed. The function accepts both hexstrings and binary keys given as a Uint8Array. For "RC4" a key of arbitrary length can be used. It can be specified as a string (password) or as a binary key given as a Uint8Array. Important: Never reuse the same key for "RC4". As RC4 is a stream cipher, the key needs to be globally unique to maintain security. Important: Never reuse the same key/iv combination for "AES" in "CTR" mode. As AES-CTR is a stream cipher, the key/iv combination needs to be globally unique to maintain security. |
bool encrypt |
true for encryption (default). false for decryption Note: For stream ciphers like RC4 or AES-CTR there is no difference between encryption and decryption, so both values give the same result. |
cipher | An object that can be used for performing the encryption or decryption. |
var ciphertext = Crypto.cipher("RC4", null, "password").crypt("secretdata");
var decrypted = Crypto.cipher("RC4", null, "password").crypt(ciphertext);
Creates an Ecdh object that can be used for Diffie-Hellman key agreement using elliptic curves.
The supported curve is Secp256r1 also known as P-256.
The objects allocates persistent memory in the JavaScript Runtime until close or secret is called.
Ecdh | An object that can be used for performing the ECDH key agreement. |
var ecdh = Crypto.ecdh();
var localPublicKey = ecdh.public();
var remotePublicKey = "aec36e41791fabfc2ddd3223a8ef59a658a9e30cd92a5d241bbf4c18684a4a61c9aa0d1d9d3181d3022d2f64c7663000915622d4e670cce86737bb00cab5de91";
var sharedSecret = ecdh.secret(remotePublicKey);
string/Uint8Array key | The input data. The function accepts both strings and binary data as Uint8Array. |
Hash | A reference to the object itself. Useful for method chaining. |
bool binary | Optional, defaulting to false. Specifies if the function should return the hash value as a hexstring or as a binary Uint8Array. |
string/Uint8Array | The calculated hash value as a hexstring or Uint8Array, depending on the binary parameter. |
Calling this function will delete the object and free all associated memory in the JavaScript Runtime.
var digestHexString = Crypto.hash("SHA256").update("data1").update("data2").final();
var digestBinary = Crypto.hash("SHA256").update("data1").update("data2").final(true);
string/Uint8Array key | The input data. The function accepts both strings and binary data as Uint8Array. |
Hmac | A reference to the object itself. Useful for method chaining. |
bool binary | Optional, defaulting to false. Specifies if the function should return the hash value as a hexstring or as a binary Uint8Array. |
string/Uint8Array | The calculated hash value as a hexstring or Uint8Array, depending on the binary parameter. |
Calling this function will delete the object and free all associated memory in the JavaScript Runtime.
var hacHexString = Crypto.hmac("SHA256","password").update("data1").update("data2").final();
var hmacBinary = Crypto.hmac("SHA256","password").update("data1").update("data2").final(true);
Sets an explicit initialization vector. If the function is never called, an IV consisting of null bytes is used.
The following modes of operation use an initialization vector: "CTR", "CFB", "CBC", "CTS".
"AES" uses an initialization vector of 16 bytes
"DES" uses an initialization vecrot of 8 bytes
string/Uint8Array iv | The initialzation vector to be used from the next crypt operation. The function accepts both hexstrings and binary data as Uint8Array. |
cipher | A reference to the object itself. Useful for method chaining. |
Returns the current IV.
bool binary | Optional, defaulting to false. Specifies if the function should return a hexstring or a binary Uint8Array. |
string/Uint8Array | The current IV value as a hexstring or Uint8Array, depending on the binary parameter. |
string/Uint8Array data |
The data to be encrypted/decrypted. For encryption the functions accepts strings or binary data as Uint8Array. For decryption the function accepts hexstrings or binary data as Uint8Array. Depending on the algorithm and mode of operation there are restrictions on the data size that can be processed. "RC4" allows arbitrary data sizes. "AES" in "CTR" or "CTS" mode allow arbitary data sizes. All other modes of "AES" expect multiples of 16 bytes "DES" expects multiples of 8 bytes |
bool binary |
Optional, defaulting to false. If false, the function will return a hexstring for encryption and a string for decryption. Otherwise the function will return binary data as a Uint8Array. |
bool last |
Optional, defaulting to true. If true, the Cipher object will be deleted after the operation, along with all associated data in the JavaScript Runtime. if false, the object can be reused for encrypting / decrypting additional chunks of data. |
string/Uint8Array | The encrypted/decrypted data a string/hexstring or Uint8Array, depending on the binary parameter. |
var key = "73757065727375706572736563726574";
var iv = "00000000000000000000000000000000";
var plaintext = "This is the secret text to be encrypted";
// encryption using AES-128 in CTR mode
var ciphertext = Crypto.cipher("AES", "CTR", key, true).iv(iv).crypt(plaintext);
// decryption using AES-128 in CTR mode
var decrypted = Crypto.cipher("AES", "CTR", key, false).iv(iv).crypt(ciphertext);
// now decrypted contains the plain text again
Returns the local 64 byte public key for the ECDHE key agreement. The public key is sent to the remote party.
bool binary | Optional, defaulting to false. Specifies if the function should return a hexstring or a binary Uint8Array. |
string/Uint8Array | The local public key as a hexstring or Uint8Array, depending on the binary parameter. |
Calculates a 32 byte shared secret using the remote public key.
string/Uint8Array remotePublicKey |
The public key of the remote party. Must be 64 bytes of data. The functions accepts both hexstrings or binary data as Uint8Array. |
bool binary |
Optional, defaulting to false. If true, the function will return a Uint8Array. Otherwise the function will return a hexstring. |
string/Uint8Array | The 32 byte shared secret as a hexstring or Uint8Array, depending on the binary parameter. |
// This example illustrates how two parties (A and B) can calculate a shared secret.
var a = Crypto.ecdh();
var b = Crypto.ecdh();
// A and B calculate their public key and send it to each other
var publicA = a.public();
var publicB = b.public();
// A and B calculate the same shared secret using the public key of the remote party
var secretA = a.secret(publicB);
var secretB = b.secret(publicA);
log(secretA == secretB); // true
function encryptObject(obj, passphrase) {
// serialize the object
var plaintext = JSON.stringify(obj);
// calculate HMAC
var hmac = Crypto.hmac("SHA256", passphrase).update(plaintext).final();
// create random 128-Bit IV
var iv = Random.bytes(16);
// create 256-Bit encryption key from passphrase by hashing it using SHA256
var key = Crypto.hash("SHA256").update(passphrase).final();
// encrypt
var ciphertext = Crypto.cipher("AES", "CTR", key, true).iv(iv).crypt(plaintext);
return {
iv: iv,
data: ciphertext,
hmac: hmac
};
}
function decryptObject(obj, passphrase) {
if (!obj || !obj.iv || !obj.data || !obj.hmac) return null;
// create 256-Bit encryption key from passphrase by hashing it using SHA256
var key = Crypto.hash("SHA256").update(passphrase).final();
// decrypt
var plaintext = Crypto.cipher("AES", "CTR", key, false).iv(obj.iv).crypt(obj.data);
// calculate HMAC
var hmac = Crypto.hmac("SHA256", passphrase).update(plaintext).final();
// check if decryption was successfull
if (hmac == obj.hmac) {
return JSON.parse(plaintext);
}
return null;
}
var passphrase = "D4s 1s7 d4s H4us v0m N1c0l4us!!1";
var input = { text: "Hi, this is top secret. We should protect it.", x: 42 };
log("input: " + JSON.stringify(input));
var encrypted = encryptObject(input, passphrase);
log("encrypted: " + JSON.stringify(encrypted));
var decrypted = decryptObject(encrypted, passphrase);
log("decrypted: " + JSON.stringify(decrypted));
JS: input: {"text":"Hi, this is top secret. We should protect it.","x":42}
JS: encrypted: {"iv":"357bf81d63418a6fdedce56558667d29","data":"f0a454da39d7306770afc7ea781904b2d49b4adb9d4f1790898d28145503a8d2183e4c53ec4e696a95938ee1c25bf5d29b24851c45a31fc6e13842887b267c","hmac":"9502652073243900ae42a4b864b05d17c3ec18b0983e3aa9ae76099be5642bac"}
JS: decrypted: {"text":"Hi, this is top secret. We should protect it.","x":42}