{"id":32975287,"url":"https://diafygi.github.io/webcrypto-examples/","last_synced_at":"2025-11-16T17:01:23.534Z","repository":{"id":27675564,"uuid":"31161716","full_name":"diafygi/webcrypto-examples","owner":"diafygi","description":"Web Cryptography API Examples Demo: https://diafygi.github.io/webcrypto-examples/","archived":false,"fork":false,"pushed_at":"2021-03-13T08:20:42.000Z","size":120,"stargazers_count":1654,"open_issues_count":36,"forks_count":194,"subscribers_count":64,"default_branch":"master","last_synced_at":"2025-03-11T04:49:19.175Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/diafygi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-02-22T12:03:15.000Z","updated_at":"2025-03-10T04:15:50.000Z","dependencies_parsed_at":"2022-07-13T12:00:59.841Z","dependency_job_id":null,"html_url":"https://github.com/diafygi/webcrypto-examples","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/diafygi/webcrypto-examples","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/diafygi%2Fwebcrypto-examples","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/diafygi%2Fwebcrypto-examples/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/diafygi%2Fwebcrypto-examples/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/diafygi%2Fwebcrypto-examples/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/diafygi","download_url":"https://codeload.github.com/diafygi/webcrypto-examples/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/diafygi%2Fwebcrypto-examples/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":284742551,"owners_count":27056072,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-16T02:00:05.974Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-11-13T06:00:26.562Z","updated_at":"2025-11-16T17:01:23.526Z","avatar_url":"https://github.com/diafygi.png","language":"HTML","funding_links":[],"categories":["Development APIs"],"sub_categories":["Cryptography"],"readme":"# Web Cryptography API Examples\n\nLive Table: https://diafygi.github.io/webcrypto-examples/\n\nI couldn't find anywhere that had clear examples of WebCryptoAPI, so I\nwrote examples and made a live table with them. Pull requests welcome!\n\n1. [RSASSA-PKCS1-v1_5](#rsassa-pkcs1-v1_5)\n  * [generateKey](#rsassa-pkcs1-v1_5---generatekey) |\n[importKey](#rsassa-pkcs1-v1_5---importkey) |\n[exportKey](#rsassa-pkcs1-v1_5---exportkey) |\n[sign](#rsassa-pkcs1-v1_5---sign) |\n[verify](#rsassa-pkcs1-v1_5---verify)\n\n2. [RSA-PSS](#rsa-pss)\n  * [generateKey](#rsa-pss---generatekey) |\n[importKey](#rsa-pss---importkey) |\n[exportKey](#rsa-pss---exportkey) |\n[sign](#rsa-pss---sign) |\n[verify](#rsa-pss---verify)\n\n3. [RSA-OAEP](#rsa-oaep)\n  * [generateKey](#rsa-oaep---generatekey) |\n[importKey](#rsa-oaep---importkey) |\n[exportKey](#rsa-oaep---exportkey) |\n[encrypt](#rsa-oaep---encrypt) |\n[decrypt](#rsa-oaep---decrypt) |\n[wrapKey](#rsa-oaep---wrapkey) |\n[unwrapKey](#rsa-oaep---unwrapkey)\n\n4. [ECDSA](#ecdsa)\n  * [generateKey](#ecdsa---generatekey) |\n[importKey](#ecdsa---importkey) |\n[exportKey](#ecdsa---exportkey) |\n[sign](#ecdsa---sign) |\n[verify](#ecdsa---verify)\n\n5. [ECDH](#ecdh)\n  * [generateKey](#ecdh---generatekey) |\n[importKey](#ecdh---importkey) |\n[exportKey](#ecdh---exportkey) |\n[deriveKey](#ecdh---derivekey) |\n[deriveBits](#ecdh---derivebits)\n\n6. [AES-CTR](#aes-ctr)\n  * [generateKey](#aes-ctr---generatekey) |\n[importKey](#aes-ctr---importkey) |\n[exportKey](#aes-ctr---exportkey) |\n[encrypt](#aes-ctr---encrypt) |\n[decrypt](#aes-ctr---decrypt) |\n[wrapKey](#aes-ctr---wrapkey) |\n[unwrapKey](#aes-ctr---unwrapkey)\n\n7. [AES-CBC](#aes-cbc)\n  * [generateKey](#aes-cbc---generatekey) |\n[importKey](#aes-cbc---importkey) |\n[exportKey](#aes-cbc---exportkey) |\n[encrypt](#aes-cbc---encrypt) |\n[decrypt](#aes-cbc---decrypt) |\n[wrapKey](#aes-cbc---wrapkey) |\n[unwrapKey](#aes-cbc---unwrapkey)\n\n8. [AES-CMAC](#aes-cmac)\n  * [generateKey](#aes-cmac---generatekey) |\n[importKey](#aes-cmac---importkey) |\n[exportKey](#aes-cmac---exportkey) |\n[sign](#aes-cmac---sign) |\n[verify](#aes-cmac---verify)\n\n9. [AES-GCM](#aes-gcm)\n  * [generateKey](#aes-gcm---generatekey) |\n[importKey](#aes-gcm---importkey) |\n[exportKey](#aes-gcm---exportkey) |\n[encrypt](#aes-gcm---encrypt) |\n[decrypt](#aes-gcm---decrypt) |\n[wrapKey](#aes-gcm---wrapkey) |\n[unwrapKey](#aes-gcm---unwrapkey)\n\n10. [AES-CFB](#aes-cfb)\n  * [generateKey](#aes-cfb---generatekey) |\n[importKey](#aes-cfb---importkey) |\n[exportKey](#aes-cfb---exportkey) |\n[encrypt](#aes-cfb---encrypt) |\n[decrypt](#aes-cfb---decrypt) |\n[wrapKey](#aes-cfb---wrapkey) |\n[unwrapKey](#aes-cfb---unwrapkey)\n\n11. [AES-KW](#aes-kw)\n  * [generateKey](#aes-kw---generatekey) |\n[importKey](#aes-kw---importkey) |\n[exportKey](#aes-kw---exportkey) |\n[wrapKey](#aes-kw---wrapkey) |\n[unwrapKey](#aes-kw---unwrapkey)\n\n12. [HMAC](#hmac)\n  * [generateKey](#hmac---generatekey) |\n[importKey](#hmac---importkey) |\n[exportKey](#hmac---exportkey) |\n[sign](#hmac---sign) |\n[verify](#hmac-verify)\n\n13. [DH](#dh)\n  * [generateKey](#dh---generatekey) |\n[importKey](#dh---importkey) |\n[exportKey](#dh---exportkey) |\n[deriveKey](#dh---derivekey) |\n[deriveBits](#dh---derivebits)\n\n14. [SHA](#sha-1)\n  * [SHA-1 digest](#sha-1---digest) |\n[SHA-256 digest](#sha-256---digest) |\n[SHA-384 digest](#sha-384---digest) |\n[SHA-512 digest](#sha-512---digest)\n\n18. [CONCAT](#concat)\n  * [importKey](#concat---importkey) |\n[deriveKey](#concat---derivekey) |\n[deriveBits](#concat---derivebits)\n\n19. [HKDF-CTR](#hkdf-ctr)\n  * [importKey](#hkdf-ctr---importkey) |\n[deriveKey](#hkdf-ctr---derivekey) |\n[deriveBits](#hkdf-ctr---derivebits)\n\n20. [PBKDF2](#pbkdf2)\n  * [generateKey](#pbkdf2---generatekey) |\n[importKey](#pbkdf2---importkey) |\n[deriveKey](#pbkdf2---derivekey) |\n[deriveBits](#pbkdf2---derivebits)\n\n## RSASSA-PKCS1-v1_5\n#### RSASSA-PKCS1-v1_5 - generateKey\n```javascript\nwindow.crypto.subtle.generateKey(\n    {\n        name: \"RSASSA-PKCS1-v1_5\",\n        modulusLength: 2048, //can be 1024, 2048, or 4096\n        publicExponent: new Uint8Array([0x01, 0x00, 0x01]),\n        hash: {name: \"SHA-256\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"sign\", \"verify\"] //can be any combination of \"sign\" and \"verify\"\n)\n.then(function(key){\n    //returns a keypair object\n    console.log(key);\n    console.log(key.publicKey);\n    console.log(key.privateKey);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### RSASSA-PKCS1-v1_5 - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"jwk\", //can be \"jwk\" (public or private), \"spki\" (public only), or \"pkcs8\" (private only)\n    {   //this is an example jwk key, other key types are Uint8Array objects\n        kty: \"RSA\",\n        e: \"AQAB\",\n        n: \"vGO3eU16ag9zRkJ4AK8ZUZrjbtp5xWK0LyFMNT8933evJoHeczexMUzSiXaLrEFSyQZortk81zJH3y41MBO_UFDO_X0crAquNrkjZDrf9Scc5-MdxlWU2Jl7Gc4Z18AC9aNibWVmXhgvHYkEoFdLCFG-2Sq-qIyW4KFkjan05IE\",\n        alg: \"RS256\",\n        ext: true,\n    },\n    {   //these are the algorithm options\n        name: \"RSASSA-PKCS1-v1_5\",\n        hash: {name: \"SHA-256\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"verify\"] //\"verify\" for public key import, \"sign\" for private key imports\n)\n.then(function(publicKey){\n    //returns a publicKey (or privateKey if you are importing a private key)\n    console.log(publicKey);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### RSASSA-PKCS1-v1_5 - exportKey\n```javascript\nwindow.crypto.subtle.exportKey(\n    \"jwk\", //can be \"jwk\" (public or private), \"spki\" (public only), or \"pkcs8\" (private only)\n    publicKey //can be a publicKey or privateKey, as long as extractable was true\n)\n.then(function(keydata){\n    //returns the exported key data\n    console.log(keydata);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### RSASSA-PKCS1-v1_5 - sign\n```javascript\nwindow.crypto.subtle.sign(\n    {\n        name: \"RSASSA-PKCS1-v1_5\",\n    },\n    privateKey, //from generateKey or importKey above\n    data //ArrayBuffer of data you want to sign\n)\n.then(function(signature){\n    //returns an ArrayBuffer containing the signature\n    console.log(new Uint8Array(signature));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### RSASSA-PKCS1-v1_5 - verify\n```javascript\nwindow.crypto.subtle.verify(\n    {\n        name: \"RSASSA-PKCS1-v1_5\",\n    },\n    publicKey, //from generateKey or importKey above\n    signature, //ArrayBuffer of the signature\n    data //ArrayBuffer of the data\n)\n.then(function(isvalid){\n    //returns a boolean on whether the signature is true or not\n    console.log(isvalid);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## RSA-PSS\n#### RSA-PSS - generateKey\n```javascript\nwindow.crypto.subtle.generateKey(\n    {\n        name: \"RSA-PSS\",\n        modulusLength: 2048, //can be 1024, 2048, or 4096\n        publicExponent: new Uint8Array([0x01, 0x00, 0x01]),\n        hash: {name: \"SHA-256\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"sign\", \"verify\"] //can be any combination of \"sign\" and \"verify\"\n)\n.then(function(key){\n    //returns a keypair object\n    console.log(key);\n    console.log(key.publicKey);\n    console.log(key.privateKey);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### RSA-PSS - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"jwk\", //can be \"jwk\" (public or private), \"spki\" (public only), or \"pkcs8\" (private only)\n    {   //this is an example jwk key, other key types are Uint8Array objects\n        kty: \"RSA\",\n        e: \"AQAB\",\n        n: \"vGO3eU16ag9zRkJ4AK8ZUZrjbtp5xWK0LyFMNT8933evJoHeczexMUzSiXaLrEFSyQZortk81zJH3y41MBO_UFDO_X0crAquNrkjZDrf9Scc5-MdxlWU2Jl7Gc4Z18AC9aNibWVmXhgvHYkEoFdLCFG-2Sq-qIyW4KFkjan05IE\",\n        alg: \"PS256\",\n        ext: true,\n    },\n    {   //these are the algorithm options\n        name: \"RSA-PSS\",\n        hash: {name: \"SHA-256\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"verify\"] //\"verify\" for public key import, \"sign\" for private key imports\n)\n.then(function(publicKey){\n    //returns a publicKey (or privateKey if you are importing a private key)\n    console.log(publicKey);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### RSA-PSS - exportKey\n```javascript\nwindow.crypto.subtle.exportKey(\n    \"jwk\", //can be \"jwk\" (public or private), \"spki\" (public only), or \"pkcs8\" (private only)\n    publicKey //can be a publicKey or privateKey, as long as extractable was true\n)\n.then(function(keydata){\n    //returns the exported key data\n    console.log(keydata);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### RSA-PSS - sign\n```javascript\nwindow.crypto.subtle.sign(\n    {\n        name: \"RSA-PSS\",\n        saltLength: 128, //the length of the salt\n    },\n    privateKey, //from generateKey or importKey above\n    data //ArrayBuffer of data you want to sign\n)\n.then(function(signature){\n    //returns an ArrayBuffer containing the signature\n    console.log(new Uint8Array(signature));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### RSA-PSS - verify\n```javascript\nwindow.crypto.subtle.verify(\n    {\n        name: \"RSA-PSS\",\n        saltLength: 128, //the length of the salt\n    },\n    publicKey, //from generateKey or importKey above\n    signature, //ArrayBuffer of the signature\n    data //ArrayBuffer of the data\n)\n.then(function(isvalid){\n    //returns a boolean on whether the signature is true or not\n    console.log(isvalid);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## RSA-OAEP\n#### RSA-OAEP - generateKey\n```javascript\nwindow.crypto.subtle.generateKey(\n    {\n        name: \"RSA-OAEP\",\n        modulusLength: 2048, //can be 1024, 2048, or 4096\n        publicExponent: new Uint8Array([0x01, 0x00, 0x01]),\n        hash: {name: \"SHA-256\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //must be [\"encrypt\", \"decrypt\"] or [\"wrapKey\", \"unwrapKey\"]\n)\n.then(function(key){\n    //returns a keypair object\n    console.log(key);\n    console.log(key.publicKey);\n    console.log(key.privateKey);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### RSA-OAEP - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"jwk\", //can be \"jwk\" (public or private), \"spki\" (public only), or \"pkcs8\" (private only)\n    {   //this is an example jwk key, other key types are Uint8Array objects\n        kty: \"RSA\",\n        e: \"AQAB\",\n        n: \"vGO3eU16ag9zRkJ4AK8ZUZrjbtp5xWK0LyFMNT8933evJoHeczexMUzSiXaLrEFSyQZortk81zJH3y41MBO_UFDO_X0crAquNrkjZDrf9Scc5-MdxlWU2Jl7Gc4Z18AC9aNibWVmXhgvHYkEoFdLCFG-2Sq-qIyW4KFkjan05IE\",\n        alg: \"RSA-OAEP-256\",\n        ext: true,\n    },\n    {   //these are the algorithm options\n        name: \"RSA-OAEP\",\n        hash: {name: \"SHA-256\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\"] //\"encrypt\" or \"wrapKey\" for public key import or\n                //\"decrypt\" or \"unwrapKey\" for private key imports\n)\n.then(function(publicKey){\n    //returns a publicKey (or privateKey if you are importing a private key)\n    console.log(publicKey);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### RSA-OAEP - exportKey\n```javascript\nwindow.crypto.subtle.exportKey(\n    \"jwk\", //can be \"jwk\" (public or private), \"spki\" (public only), or \"pkcs8\" (private only)\n    publicKey //can be a publicKey or privateKey, as long as extractable was true\n)\n.then(function(keydata){\n    //returns the exported key data\n    console.log(keydata);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### RSA-OAEP - encrypt\n```javascript\nwindow.crypto.subtle.encrypt(\n    {\n        name: \"RSA-OAEP\",\n        //label: Uint8Array([...]) //optional\n    },\n    publicKey, //from generateKey or importKey above\n    data //ArrayBuffer of data you want to encrypt\n)\n.then(function(encrypted){\n    //returns an ArrayBuffer containing the encrypted data\n    console.log(new Uint8Array(encrypted));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### RSA-OAEP - decrypt\n```javascript\nwindow.crypto.subtle.decrypt(\n    {\n        name: \"RSA-OAEP\",\n        //label: Uint8Array([...]) //optional\n    },\n    privateKey, //from generateKey or importKey above\n    data //ArrayBuffer of the data\n)\n.then(function(decrypted){\n    //returns an ArrayBuffer containing the decrypted data\n    console.log(new Uint8Array(decrypted));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### RSA-OAEP - wrapKey\n```javascript\nwindow.crypto.subtle.wrapKey(\n    \"raw\", //the export format, must be \"raw\" (only available sometimes)\n    key, //the key you want to wrap, must be able to fit in RSA-OAEP padding\n    publicKey, //the public key with \"wrapKey\" usage flag\n    {   //these are the wrapping key's algorithm options\n        name: \"RSA-OAEP\",\n        hash: {name: \"SHA-256\"},\n    }\n)\n.then(function(wrapped){\n    //returns an ArrayBuffer containing the encrypted data\n    console.log(new Uint8Array(wrapped));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### RSA-OAEP - unwrapKey\n```javascript\nwindow.crypto.subtle.unwrapKey(\n    \"raw\", //the import format, must be \"raw\" (only available sometimes)\n    wrapped, //the key you want to unwrap\n    privateKey, //the private key with \"unwrapKey\" usage flag\n    {   //these are the wrapping key's algorithm options\n        name: \"RSA-OAEP\",\n        modulusLength: 2048,\n        publicExponent: new Uint8Array([0x01, 0x00, 0x01]),\n        hash: {name: \"SHA-256\"},\n    },\n    {   //this what you want the wrapped key to become (same as when wrapping)\n        name: \"AES-GCM\",\n        length: 256\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //the usages you want the unwrapped key to have\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## ECDSA\n#### ECDSA - generateKey\n```javascript\nwindow.crypto.subtle.generateKey(\n    {\n        name: \"ECDSA\",\n        namedCurve: \"P-256\", //can be \"P-256\", \"P-384\", or \"P-521\"\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"sign\", \"verify\"] //can be any combination of \"sign\" and \"verify\"\n)\n.then(function(key){\n    //returns a keypair object\n    console.log(key);\n    console.log(key.publicKey);\n    console.log(key.privateKey);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### ECDSA - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"jwk\", //can be \"jwk\" (public or private), \"spki\" (public only), or \"pkcs8\" (private only)\n    {   //this is an example jwk key, other key types are Uint8Array objects\n        kty: \"EC\",\n        crv: \"P-256\",\n        x: \"zCQ5BPHPCLZYgdpo1n-x_90P2Ij52d53YVwTh3ZdiMo\",\n        y: \"pDfQTUx0-OiZc5ZuKMcA7v2Q7ZPKsQwzB58bft0JTko\",\n        ext: true,\n    },\n    {   //these are the algorithm options\n        name: \"ECDSA\",\n        namedCurve: \"P-256\", //can be \"P-256\", \"P-384\", or \"P-521\"\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"verify\"] //\"verify\" for public key import, \"sign\" for private key imports\n)\n.then(function(publicKey){\n    //returns a publicKey (or privateKey if you are importing a private key)\n    console.log(publicKey);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### ECDSA - exportKey\n```javascript\nwindow.crypto.subtle.exportKey(\n    \"jwk\", //can be \"jwk\" (public or private), \"spki\" (public only), or \"pkcs8\" (private only)\n    publicKey //can be a publicKey or privateKey, as long as extractable was true\n)\n.then(function(keydata){\n    //returns the exported key data\n    console.log(keydata);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### ECDSA - sign\n```javascript\nwindow.crypto.subtle.sign(\n    {\n        name: \"ECDSA\",\n        hash: {name: \"SHA-256\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n    },\n    privateKey, //from generateKey or importKey above\n    data //ArrayBuffer of data you want to sign\n)\n.then(function(signature){\n    //returns an ArrayBuffer containing the signature\n    console.log(new Uint8Array(signature));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### ECDSA - verify\n```javascript\nwindow.crypto.subtle.verify(\n    {\n        name: \"ECDSA\",\n        hash: {name: \"SHA-256\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n    },\n    publicKey, //from generateKey or importKey above\n    signature, //ArrayBuffer of the signature\n    data //ArrayBuffer of the data\n)\n.then(function(isvalid){\n    //returns a boolean on whether the signature is true or not\n    console.log(isvalid);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## ECDH\n#### ECDH - generateKey\n```javascript\nwindow.crypto.subtle.generateKey(\n    {\n        name: \"ECDH\",\n        namedCurve: \"P-256\", //can be \"P-256\", \"P-384\", or \"P-521\"\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"deriveKey\", \"deriveBits\"] //can be any combination of \"deriveKey\" and \"deriveBits\"\n)\n.then(function(key){\n    //returns a keypair object\n    console.log(key);\n    console.log(key.publicKey);\n    console.log(key.privateKey);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### ECDH - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"jwk\", //can be \"jwk\" (public or private), \"raw\" (public only), \"spki\" (public only), or \"pkcs8\" (private only)\n    {   //this is an example jwk key, other key types are Uint8Array objects\n        kty: \"EC\",\n        crv: \"P-256\",\n        x: \"kgR_PqO07L8sZOBbw6rvv7O_f7clqDeiE3WnMkb5EoI\",\n        y: \"djI-XqCqSyO9GFk_QT_stROMCAROIvU8KOORBgQUemE\",\n        d: \"5aPFSt0UFVXYGu-ZKyC9FQIUOAMmnjzdIwkxCMe3Iok\",\n        ext: true,\n    },\n    {   //these are the algorithm options\n        name: \"ECDH\",\n        namedCurve: \"P-256\", //can be \"P-256\", \"P-384\", or \"P-521\"\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"deriveKey\", \"deriveBits\"] //\"deriveKey\" and/or \"deriveBits\" for private keys only (just put an empty list if importing a public key)\n)\n.then(function(privateKey){\n    //returns a privateKey (or publicKey if you are importing a public key)\n    console.log(privateKey);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### ECDH - exportKey\n```javascript\nwindow.crypto.subtle.exportKey(\n    \"jwk\", //can be \"jwk\" (public or private), \"raw\" (public only), \"spki\" (public only), or \"pkcs8\" (private only)\n    publicKey //can be a publicKey or privateKey, as long as extractable was true\n)\n.then(function(keydata){\n    //returns the exported key data\n    console.log(keydata);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### ECDH - deriveKey\n```javascript\nwindow.crypto.subtle.deriveKey(\n    {\n        name: \"ECDH\",\n        namedCurve: \"P-256\", //can be \"P-256\", \"P-384\", or \"P-521\"\n        public: publicKey, //an ECDH public key from generateKey or importKey\n    },\n    privateKey, //your ECDH private key from generateKey or importKey\n    { //the key type you want to create based on the derived bits\n        name: \"AES-CTR\", //can be any AES algorithm (\"AES-CTR\", \"AES-CBC\", \"AES-CMAC\", \"AES-GCM\", \"AES-CFB\", \"AES-KW\", \"ECDH\", \"DH\", or \"HMAC\")\n        //the generateKey parameters for that type of algorithm\n        length: 256, //can be  128, 192, or 256\n    },\n    false, //whether the derived key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //limited to the options in that algorithm's importKey\n)\n.then(function(keydata){\n    //returns the exported key data\n    console.log(keydata);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### ECDH - deriveBits\n```javascript\nwindow.crypto.subtle.deriveBits(\n    {\n        name: \"ECDH\",\n        namedCurve: \"P-256\", //can be \"P-256\", \"P-384\", or \"P-521\"\n        public: publicKey, //an ECDH public key from generateKey or importKey\n    },\n    privateKey, //your ECDH private key from generateKey or importKey\n    256 //the number of bits you want to derive\n)\n.then(function(bits){\n    //returns the derived bits as an ArrayBuffer\n    console.log(new Uint8Array(bits));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## AES-CTR\n#### AES-CTR - generateKey\n```javascript\nwindow.crypto.subtle.generateKey(\n    {\n        name: \"AES-CTR\",\n        length: 256, //can be  128, 192, or 256\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //can \"encrypt\", \"decrypt\", \"wrapKey\", or \"unwrapKey\"\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CTR - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"jwk\", //can be \"jwk\" or \"raw\"\n    {   //this is an example jwk key, \"raw\" would be an ArrayBuffer\n        kty: \"oct\",\n        k: \"Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE\",\n        alg: \"A256CTR\",\n        ext: true,\n    },\n    {   //this is the algorithm options\n        name: \"AES-CTR\",\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //can \"encrypt\", \"decrypt\", \"wrapKey\", or \"unwrapKey\"\n)\n.then(function(key){\n    //returns the symmetric key\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CTR - exportKey\n```javascript\nwindow.crypto.subtle.exportKey(\n    \"jwk\", //can be \"jwk\" or \"raw\"\n    key //extractable must be true\n)\n.then(function(keydata){\n    //returns the exported key data\n    console.log(keydata);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CTR - encrypt\n```javascript\nwindow.crypto.subtle.encrypt(\n    {\n        name: \"AES-CTR\",\n        //Don't re-use counters!\n        //Always use a new counter every time your encrypt!\n        counter: new Uint8Array(16),\n        length: 128, //can be 1-128\n    },\n    key, //from generateKey or importKey above\n    data //ArrayBuffer of data you want to encrypt\n)\n.then(function(encrypted){\n    //returns an ArrayBuffer containing the encrypted data\n    console.log(new Uint8Array(encrypted));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CTR - decrypt\n```javascript\nwindow.crypto.subtle.decrypt(\n    {\n        name: \"AES-CTR\",\n        counter: ArrayBuffer(16), //The same counter you used to encrypt\n        length: 128, //The same length you used to encrypt\n    },\n    key, //from generateKey or importKey above\n    data //ArrayBuffer of the data\n)\n.then(function(decrypted){\n    //returns an ArrayBuffer containing the decrypted data\n    console.log(new Uint8Array(decrypted));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CTR - wrapKey\n```javascript\nwindow.crypto.subtle.wrapKey(\n    \"jwk\", //can be \"jwk\", \"raw\", \"spki\", or \"pkcs8\"\n    key, //the key you want to wrap, must be able to export to \"raw\" format\n    wrappingKey, //the AES-CTR key with \"wrapKey\" usage flag\n    {   //these are the wrapping key's algorithm options\n        name: \"AES-CTR\",\n        //Don't re-use counters!\n        //Always use a new counter every time your encrypt!\n        counter: new Uint8Array(16),\n        length: 128, //can be 1-128\n    }\n)\n.then(function(wrapped){\n    //returns an ArrayBuffer containing the encrypted data\n    console.log(new Uint8Array(wrapped));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CTR - unwrapKey\n```javascript\nwindow.crypto.subtle.unwrapKey(\n    \"jwk\", //\"jwk\", \"raw\", \"spki\", or \"pkcs8\" (whatever was used in wrapping)\n    wrapped, //the key you want to unwrap\n    wrappingKey, //the AES-CTR key with \"unwrapKey\" usage flag\n    {   //these are the wrapping key's algorithm options\n        name: \"AES-CTR\",\n        //Don't re-use counters!\n        //Always use a new counter every time your encrypt!\n        counter: new Uint8Array(16),\n        length: 128, //can be 1-128\n    },\n    {   //this what you want the wrapped key to become (same as when wrapping)\n        name: \"AES-GCM\",\n        length: 256\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //the usages you want the unwrapped key to have\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## AES-CBC\n#### AES-CBC - generateKey\n```javascript\nwindow.crypto.subtle.generateKey(\n    {\n        name: \"AES-CBC\",\n        length: 256, //can be  128, 192, or 256\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //can be \"encrypt\", \"decrypt\", \"wrapKey\", or \"unwrapKey\"\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CBC - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"jwk\", //can be \"jwk\" or \"raw\"\n    {   //this is an example jwk key, \"raw\" would be an ArrayBuffer\n        kty: \"oct\",\n        k: \"Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE\",\n        alg: \"A256CBC\",\n        ext: true,\n    },\n    {   //this is the algorithm options\n        name: \"AES-CBC\",\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //can be \"encrypt\", \"decrypt\", \"wrapKey\", or \"unwrapKey\"\n)\n.then(function(key){\n    //returns the symmetric key\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CBC - exportKey\n```javascript\nwindow.crypto.subtle.exportKey(\n    \"jwk\", //can be \"jwk\" or \"raw\"\n    key //extractable must be true\n)\n.then(function(keydata){\n    //returns the exported key data\n    console.log(keydata);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CBC - encrypt\n```javascript\nwindow.crypto.subtle.encrypt(\n    {\n        name: \"AES-CBC\",\n        //Don't re-use initialization vectors!\n        //Always generate a new iv every time your encrypt!\n        iv: window.crypto.getRandomValues(new Uint8Array(16)),\n    },\n    key, //from generateKey or importKey above\n    data //ArrayBuffer of data you want to encrypt\n)\n.then(function(encrypted){\n    //returns an ArrayBuffer containing the encrypted data\n    console.log(new Uint8Array(encrypted));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CBC - decrypt\n```javascript\nwindow.crypto.subtle.decrypt(\n    {\n        name: \"AES-CBC\",\n        iv: ArrayBuffer(16), //The initialization vector you used to encrypt\n    },\n    key, //from generateKey or importKey above\n    data //ArrayBuffer of the data\n)\n.then(function(decrypted){\n    //returns an ArrayBuffer containing the decrypted data\n    console.log(new Uint8Array(decrypted));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CBC - wrapKey\n```javascript\nwindow.crypto.subtle.wrapKey(\n    \"jwk\", //can be \"jwk\", \"raw\", \"spki\", or \"pkcs8\"\n    key, //the key you want to wrap, must be able to export to above format\n    wrappingKey, //the AES-CBC key with \"wrapKey\" usage flag\n    {   //these are the wrapping key's algorithm options\n        name: \"AES-CBC\",\n        //Don't re-use initialization vectors!\n        //Always generate a new iv every time your encrypt!\n        iv: window.crypto.getRandomValues(new Uint8Array(16)),\n    }\n)\n.then(function(wrapped){\n    //returns an ArrayBuffer containing the encrypted data\n    console.log(new Uint8Array(wrapped));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CBC - unwrapKey\n```javascript\nwindow.crypto.subtle.unwrapKey(\n    \"jwk\", //\"jwk\", \"raw\", \"spki\", or \"pkcs8\" (whatever was used in wrapping)\n    wrapped, //the key you want to unwrap\n    wrappingKey, //the AES-CBC key with \"unwrapKey\" usage flag\n    {   //these are the wrapping key's algorithm options\n        name: \"AES-CBC\",\n        iv: ArrayBuffer(16), //The initialization vector you used to encrypt\n    },\n    {   //this what you want the wrapped key to become (same as when wrapping)\n        name: \"AES-GCM\",\n        length: 256\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //the usages you want the unwrapped key to have\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## AES-CMAC\n#### AES-CMAC - generateKey\n```javascript\nwindow.crypto.subtle.generateKey(\n    {\n        name: \"AES-CMAC\",\n        length: 256, //can be  128, 192, or 256\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"sign\", \"verify\"] //can be any combination of \"sign\" and \"verify\"\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CMAC - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"jwk\", //can be \"jwk\" or \"raw\"\n    {   //this is an example jwk key, \"raw\" would be an ArrayBuffer\n        kty: \"oct\",\n        k: \"Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE\",\n        alg: \"A256CMAC\",\n        ext: true,\n    },\n    {   //this is the algorithm options\n        name: \"AES-CMAC\",\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"sign\", \"verify\"] //can be any combination of \"sign\" and \"verify\"\n)\n.then(function(key){\n    //returns the symmetric key\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CMAC - exportKey\n```javascript\nwindow.crypto.subtle.exportKey(\n    \"jwk\", //can be \"jwk\" or \"raw\"\n    key //extractable must be true\n)\n.then(function(keydata){\n    //returns the exported key data\n    console.log(keydata);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CMAC - sign\n```javascript\nwindow.crypto.subtle.sign(\n    {\n        name: \"AES-CMAC\",\n        length: 256, //bit length of the MAC\n    },\n    key, //from generateKey or importKey above\n    data //ArrayBuffer of data you want to sign\n)\n.then(function(signature){\n    //returns an ArrayBuffer containing the signature\n    console.log(new Uint8Array(signature));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CMAC - verify\n```javascript\nwindow.crypto.subtle.verify(\n    {\n        name: \"AES-CMAC\",\n        length: 256, //bit length of the MAC\n    },\n    key, //from generateKey or importKey above\n    signature, //ArrayBuffer of the signature\n    data //ArrayBuffer of the data\n)\n.then(function(isvalid){\n    //returns a boolean on whether the signature is true or not\n    console.log(isvalid);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## AES-GCM\n#### AES-GCM - generateKey\n```javascript\nwindow.crypto.subtle.generateKey(\n    {\n        name: \"AES-GCM\",\n        length: 256, //can be  128, 192, or 256\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //can \"encrypt\", \"decrypt\", \"wrapKey\", or \"unwrapKey\"\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-GCM - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"jwk\", //can be \"jwk\" or \"raw\"\n    {   //this is an example jwk key, \"raw\" would be an ArrayBuffer\n        kty: \"oct\",\n        k: \"Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE\",\n        alg: \"A256GCM\",\n        ext: true,\n    },\n    {   //this is the algorithm options\n        name: \"AES-GCM\",\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //can \"encrypt\", \"decrypt\", \"wrapKey\", or \"unwrapKey\"\n)\n.then(function(key){\n    //returns the symmetric key\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-GCM - exportKey\n```javascript\nwindow.crypto.subtle.exportKey(\n    \"jwk\", //can be \"jwk\" or \"raw\"\n    key //extractable must be true\n)\n.then(function(keydata){\n    //returns the exported key data\n    console.log(keydata);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-GCM - encrypt\n```javascript\nwindow.crypto.subtle.encrypt(\n    {\n        name: \"AES-GCM\",\n\n        //Don't re-use initialization vectors!\n        //Always generate a new iv every time your encrypt!\n        //Recommended to use 12 bytes length\n        iv: window.crypto.getRandomValues(new Uint8Array(12)),\n\n        //Additional authentication data (optional)\n        additionalData: ArrayBuffer,\n\n        //Tag length (optional)\n        tagLength: 128, //can be 32, 64, 96, 104, 112, 120 or 128 (default)\n    },\n    key, //from generateKey or importKey above\n    data //ArrayBuffer of data you want to encrypt\n)\n.then(function(encrypted){\n    //returns an ArrayBuffer containing the encrypted data\n    console.log(new Uint8Array(encrypted));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-GCM - decrypt\n```javascript\nwindow.crypto.subtle.decrypt(\n    {\n        name: \"AES-GCM\",\n        iv: ArrayBuffer(12), //The initialization vector you used to encrypt\n        additionalData: ArrayBuffer, //The addtionalData you used to encrypt (if any)\n        tagLength: 128, //The tagLength you used to encrypt (if any)\n    },\n    key, //from generateKey or importKey above\n    data //ArrayBuffer of the data\n)\n.then(function(decrypted){\n    //returns an ArrayBuffer containing the decrypted data\n    console.log(new Uint8Array(decrypted));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-GCM - wrapKey\n```javascript\nwindow.crypto.subtle.wrapKey(\n    \"jwk\", //can be \"jwk\", \"raw\", \"spki\", or \"pkcs8\"\n    key, //the key you want to wrap, must be able to export to above format\n    wrappingKey, //the AES-GCM key with \"wrapKey\" usage flag\n    {   //these are the wrapping key's algorithm options\n        name: \"AES-GCM\",\n\n        //Don't re-use initialization vectors!\n        //Always generate a new iv every time your encrypt!\n        //Recommended to use 12 bytes length\n        iv: window.crypto.getRandomValues(new Uint8Array(12)),\n\n        //Additional authentication data (optional)\n        additionalData: ArrayBuffer,\n\n        //Tag length (optional)\n        tagLength: 128, //can be 32, 64, 96, 104, 112, 120 or 128 (default)\n    }\n)\n.then(function(wrapped){\n    //returns an ArrayBuffer containing the encrypted data\n    console.log(new Uint8Array(wrapped));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-GCM - unwrapKey\n```javascript\nwindow.crypto.subtle.unwrapKey(\n    \"jwk\", //\"jwk\", \"raw\", \"spki\", or \"pkcs8\" (whatever was used in wrapping)\n    wrapped, //the key you want to unwrap\n    wrappingKey, //the AES-GCM key with \"unwrapKey\" usage flag\n    {   //these are the wrapping key's algorithm options\n        name: \"AES-GCM\",\n        iv: ArrayBuffer(12), //The initialization vector you used to encrypt\n        additionalData: ArrayBuffer, //The addtionalData you used to encrypt (if any)\n        tagLength: 128, //The tagLength you used to encrypt (if any)\n    },\n    {   //this what you want the wrapped key to become (same as when wrapping)\n        name: \"AES-CBC\",\n        length: 256\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //the usages you want the unwrapped key to have\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## AES-CFB\n#### AES-CFB - generateKey\n```javascript\nwindow.crypto.subtle.generateKey(\n    {\n        name: \"AES-CFB-8\",\n        length: 256, //can be  128, 192, or 256\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //can \"encrypt\", \"decrypt\", \"wrapKey\", or \"unwrapKey\"\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CFB - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"jwk\", //can be \"jwk\" or \"raw\"\n    {   //this is an example jwk key, \"raw\" would be an ArrayBuffer\n        kty: \"oct\",\n        k: \"Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE\",\n        alg: \"A256CFB8\",\n        ext: true,\n    },\n    {   //this is the algorithm options\n        name: \"AES-CFB-8\",\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //can \"encrypt\", \"decrypt\", \"wrapKey\", or \"unwrapKey\"\n)\n.then(function(key){\n    //returns the symmetric key\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CFB - exportKey\n```javascript\nwindow.crypto.subtle.exportKey(\n    \"jwk\", //can be \"jwk\" or \"raw\"\n    key //extractable must be true\n)\n.then(function(keydata){\n    //returns the exported key data\n    console.log(keydata);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CFB - encrypt\n```javascript\nwindow.crypto.subtle.encrypt(\n    {\n        name: \"AES-CFB-8\",\n        //Don't re-use initialization vectors!\n        //Always generate a new iv every time your encrypt!\n        iv: window.crypto.getRandomValues(new Uint8Array(16)),\n    },\n    key, //from generateKey or importKey above\n    data //ArrayBuffer of data you want to encrypt\n)\n.then(function(encrypted){\n    //returns an ArrayBuffer containing the encrypted data\n    console.log(new Uint8Array(encrypted));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CFB - decrypt\n```javascript\nwindow.crypto.subtle.decrypt(\n    {\n        name: \"AES-CFB-8\",\n        iv: ArrayBuffer(16), //The initialization vector you used to encrypt\n    },\n    key, //from generateKey or importKey above\n    data //ArrayBuffer of the data\n)\n.then(function(decrypted){\n    //returns an ArrayBuffer containing the decrypted data\n    console.log(new Uint8Array(decrypted));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CFB - wrapKey\n```javascript\nwindow.crypto.subtle.wrapKey(\n    \"jwk\", //can be \"jwk\", \"raw\", \"spki\", or \"pkcs8\"\n    key, //the key you want to wrap, must be able to export to above format\n    wrappingKey, //the AES-CFB key with \"wrapKey\" usage flag\n    {   //these are the wrapping key's algorithm options\n        name: \"AES-CFB\",\n        //Don't re-use initialization vectors!\n        //Always generate a new iv every time your encrypt!\n        iv: window.crypto.getRandomValues(new Uint8Array(16)),\n    }\n)\n.then(function(wrapped){\n    //returns an ArrayBuffer containing the encrypted data\n    console.log(new Uint8Array(wrapped));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-CFB - unwrapKey\n```javascript\nwindow.crypto.subtle.unwrapKey(\n    \"jwk\", //\"jwk\", \"raw\", \"spki\", or \"pkcs8\" (whatever was used in wrapping)\n    wrapped, //the key you want to unwrap\n    wrappingKey, //the AES-CFB key with \"unwrapKey\" usage flag\n    {   //these are the wrapping key's algorithm options\n        name: \"AES-CFB\",\n        iv: ArrayBuffer(16), //The initialization vector you used to encrypt\n    },\n    {   //this what you want the wrapped key to become (same as when wrapping)\n        name: \"AES-GCM\",\n        length: 256\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //the usages you want the unwrapped key to have\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## AES-KW\n#### AES-KW - generateKey\n```javascript\nwindow.crypto.subtle.generateKey(\n    {\n        name: \"AES-KW\",\n        length: 256, //can be  128, 192, or 256\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"wrapKey\", \"unwrapKey\"] //can be any combination of \"wrapKey\" and \"unwrapKey\"\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-KW - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"jwk\", //can be \"jwk\" or \"raw\"\n    {   //this is an example jwk key, \"raw\" would be an ArrayBuffer\n        kty: \"oct\",\n        k: \"Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE\",\n        alg: \"A256KW\",\n        ext: true,\n    },\n    {   //this is the algorithm options\n        name: \"AES-KW\",\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"wrapKey\", \"unwrapKey\"] //can be any combination of \"wrapKey\" and \"unwrapKey\"\n)\n.then(function(key){\n    //returns the symmetric key\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-KW - exportKey\n```javascript\nwindow.crypto.subtle.exportKey(\n    \"jwk\", //can be \"jwk\" or \"raw\"\n    key //extractable must be true\n)\n.then(function(keydata){\n    //returns the exported key data\n    console.log(keydata);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-KW - wrapKey\n```javascript\nwindow.crypto.subtle.wrapKey(\n    \"raw\", //the export format, must be \"raw\" (only available sometimes)\n    key, //the key you want to wrap, must export in 8 byte increments\n    wrappingKey, //the AES-KW key with \"wrapKey\" usage flag\n    {   //these are the wrapping key's algorithm options\n        name: \"AES-KW\",\n    }\n)\n.then(function(wrapped){\n    //returns an ArrayBuffer containing the encrypted data\n    console.log(new Uint8Array(wrapped));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### AES-KW - unwrapKey\n```javascript\nwindow.crypto.subtle.unwrapKey(\n    \"raw\", //the import format, must be \"raw\" (only available sometimes)\n    wrapped, //the key you want to unwrap\n    wrappingKey, //the AES-KW key with \"unwrapKey\" usage flag\n    {   //these are the wrapping key's algorithm options\n        name: \"AES-KW\",\n    },\n    {   //this what you want the wrapped key to become (same as when wrapping)\n        name: \"AES-GCM\",\n        length: 256\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //the usages you want the unwrapped key to have\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## HMAC\n#### HMAC - generateKey\n```javascript\nwindow.crypto.subtle.generateKey(\n    {\n        name: \"HMAC\",\n        hash: {name: \"SHA-256\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n        //length: 256, //optional, if you want your key length to differ from the hash function's block length\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"sign\", \"verify\"] //can be any combination of \"sign\" and \"verify\"\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### HMAC - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"jwk\", //can be \"jwk\" or \"raw\"\n    {   //this is an example jwk key, \"raw\" would be an ArrayBuffer\n        kty: \"oct\",\n        k: \"Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE\",\n        alg: \"HS256\",\n        ext: true,\n    },\n    {   //this is the algorithm options\n        name: \"HMAC\",\n        hash: {name: \"SHA-256\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n        //length: 256, //optional, if you want your key length to differ from the hash function's block length\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"sign\", \"verify\"] //can be any combination of \"sign\" and \"verify\"\n)\n.then(function(key){\n    //returns the symmetric key\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### HMAC - exportKey\n```javascript\nwindow.crypto.subtle.exportKey(\n    \"jwk\", //can be \"jwk\" or \"raw\"\n    key //extractable must be true\n)\n.then(function(keydata){\n    //returns the exported key data\n    console.log(keydata);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### HMAC - sign\n```javascript\nwindow.crypto.subtle.sign(\n    {\n        name: \"HMAC\",\n    },\n    key, //from generateKey or importKey above\n    data //ArrayBuffer of data you want to sign\n)\n.then(function(signature){\n    //returns an ArrayBuffer containing the signature\n    console.log(new Uint8Array(signature));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### HMAC - verify\n```javascript\nwindow.crypto.subtle.verify(\n    {\n        name: \"HMAC\",\n    },\n    key, //from generateKey or importKey above\n    signature, //ArrayBuffer of the signature\n    data //ArrayBuffer of the data\n)\n.then(function(isvalid){\n    //returns a boolean on whether the signature is true or not\n    console.log(isvalid);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## DH\n#### DH - generateKey\n```javascript\nwindow.crypto.subtle.generateKey(\n    {\n        name: \"DH\",\n        //NOTE: THIS IS A SMALL PRIME FOR TESTING ONLY! DO NOT USE IT FOR REAL!\n        //See http://datatracker.ietf.org/doc/rfc3526/ for better primes\n        prime: new Uint8Array([\n            255,255,255,255,255,255,255,255,201,15,218,162,33,104,194,52,196,198,98,139,\n            128,220,28,209,41,2,78,8,138,103,204,116,2,11,190,166,59,19,155,34,81,74,8,\n            121,142,52,4,221,239,149,25,179,205,58,67,27,48,43,10,109,242,95,20,55,79,225,\n            53,109,109,81,194,69,228,133,181,118,98,94,126,198,244,76,66,233,166,55,237,\n            107,11,255,92,182,244,6,183,237,238,56,107,251,90,137,159,165,174,159,36,17,\n            124,75,31,230,73,40,102,81,236,228,91,61,194,0,124,184,161,99,191,5,152,218,\n            72,54,28,85,211,154,105,22,63,168,253,36,207,95,131,101,93,35,220,163,173,\n            150,28,98,243,86,32,133,82,187,158,213,41,7,112,150,150,109,103,12,53,78,74,\n            188,152,4,241,116,108,8,202,35,115,39,255,255,255,255,255,255,255,255\n        ]),\n        generator: new Uint8Array([2]),\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"deriveKey\", \"deriveBits\"] //can be any combination of \"deriveKey\" and \"deriveBits\"\n)\n.then(function(key){\n    //returns a keypair object\n    console.log(key);\n    console.log(key.publicKey);\n    console.log(key.privateKey);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### DH - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"raw\", //can be \"raw\" (public only), \"spki\" (public only), or \"pkcs8\" (private only)\n    new Uint8Array([ //this is an example raw key, \"raw\" would be an ArrayBuffer\n        203,25,0,203,43,75,46,159,217,37,185,181,25,220,71,187,112,195,251,233,152,56,206,\n        93,18,96,87,132,17,113,166,110,123,190,194,168,100,147,21,174,131,80,8,247,125,35,\n        210,70,103,141,152,173,99,74,34,132,92,134,216,55,171,186,89,167,189,217,164,119,\n        22,139,55,26,239,242,30,241,140,139,202,116,174,137,77,11,29,4,30,47,118,170,84,243,\n        97,132,86,58,24,82,36,149,45,185,23,172,67,162,48,43,110,251,175,20,102,237,113,148,\n        5,242,29,209,34,173,52,72,251,254,84,86,226,151,202,110,61,145,198,244,80,227,65,\n        203,118,217,91,45,58,172,165,224,122,230,50,135,120,124,37,190,186,204,103,218,19,\n        91,246,115,6,199,45,121,156,149,6,208,85,26,94,171,165,228,58,200,49,82,210,170,243,\n        154,190,15,2,225,143,159\n    ]),\n    {   //these are the algorithm options\n        name: \"DH\",\n        //NOTE: THIS IS A SMALL PRIME FOR TESTING ONLY! DO NOT USE IT FOR REAL!\n        //See http://datatracker.ietf.org/doc/rfc3526/ for better primes\n        prime: new Uint8Array([\n            255,255,255,255,255,255,255,255,201,15,218,162,33,104,194,52,196,198,98,139,\n            128,220,28,209,41,2,78,8,138,103,204,116,2,11,190,166,59,19,155,34,81,74,8,\n            121,142,52,4,221,239,149,25,179,205,58,67,27,48,43,10,109,242,95,20,55,79,225,\n            53,109,109,81,194,69,228,133,181,118,98,94,126,198,244,76,66,233,166,55,237,\n            107,11,255,92,182,244,6,183,237,238,56,107,251,90,137,159,165,174,159,36,17,\n            124,75,31,230,73,40,102,81,236,228,91,61,194,0,124,184,161,99,191,5,152,218,\n            72,54,28,85,211,154,105,22,63,168,253,36,207,95,131,101,93,35,220,163,173,\n            150,28,98,243,86,32,133,82,187,158,213,41,7,112,150,150,109,103,12,53,78,74,\n            188,152,4,241,116,108,8,202,35,115,39,255,255,255,255,255,255,255,255\n        ]),\n        generator: new Uint8Array([2]),\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [] //use [\"deriveKey\", \"deriveBits\"] if importing a private key\n)\n.then(function(publicKey){\n    //returns a publicKey (or privateKey if you are importing a private key)\n    console.log(publicKey);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### DH - exportKey\n```javascript\nwindow.crypto.subtle.exportKey(\n    \"jwk\", //can be \"raw\" (public or private), \"spki\" (public only), or \"pkcs8\" (private only)\n    publicKey //can be a publicKey or privateKey, as long as extractable was true\n)\n.then(function(keydata){\n    //returns the exported key data\n    console.log(keydata);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### DH - deriveKey\n```javascript\nwindow.crypto.subtle.deriveKey(\n    {\n        name: \"DH\",\n        //NOTE: THIS IS A SMALL PRIME FOR TESTING ONLY! DO NOT USE IT FOR REAL!\n        //See http://datatracker.ietf.org/doc/rfc3526/ for better primes\n        prime: new Uint8Array([\n            255,255,255,255,255,255,255,255,201,15,218,162,33,104,194,52,196,198,98,139,\n            128,220,28,209,41,2,78,8,138,103,204,116,2,11,190,166,59,19,155,34,81,74,8,\n            121,142,52,4,221,239,149,25,179,205,58,67,27,48,43,10,109,242,95,20,55,79,225,\n            53,109,109,81,194,69,228,133,181,118,98,94,126,198,244,76,66,233,166,55,237,\n            107,11,255,92,182,244,6,183,237,238,56,107,251,90,137,159,165,174,159,36,17,\n            124,75,31,230,73,40,102,81,236,228,91,61,194,0,124,184,161,99,191,5,152,218,\n            72,54,28,85,211,154,105,22,63,168,253,36,207,95,131,101,93,35,220,163,173,\n            150,28,98,243,86,32,133,82,187,158,213,41,7,112,150,150,109,103,12,53,78,74,\n            188,152,4,241,116,108,8,202,35,115,39,255,255,255,255,255,255,255,255\n        ]),\n        generator: new Uint8Array([2]),\n        public: publicKey, //a DH public key from generateKey or importKey\n    },\n    privateKey, //your DH private key from generateKey or importKey\n    { //the key type you want to create based on the derived bits\n        name: \"AES-CTR\", //can be any AES algorithm (\"AES-CTR\", \"AES-CBC\", \"AES-CMAC\", \"AES-GCM\", \"AES-CFB\", \"AES-KW\", \"ECDH\", \"DH\", or \"HMAC\")\n        //the generateKey parameters for that type of algorithm\n        length: 256, //can be  128, 192, or 256\n    },\n    false, //whether the derived key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //limited to the options in that algorithm's importKey\n)\n.then(function(key){\n    //returns the derived key\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### DH - deriveBits\n```javascript\nwindow.crypto.subtle.deriveBits(\n    {\n        name: \"DH\",\n        //NOTE: THIS IS A SMALL PRIME FOR TESTING ONLY! DO NOT USE IT FOR REAL!\n        //See http://datatracker.ietf.org/doc/rfc3526/ for better primes\n        prime: new Uint8Array([\n            255,255,255,255,255,255,255,255,201,15,218,162,33,104,194,52,196,198,98,139,\n            128,220,28,209,41,2,78,8,138,103,204,116,2,11,190,166,59,19,155,34,81,74,8,\n            121,142,52,4,221,239,149,25,179,205,58,67,27,48,43,10,109,242,95,20,55,79,225,\n            53,109,109,81,194,69,228,133,181,118,98,94,126,198,244,76,66,233,166,55,237,\n            107,11,255,92,182,244,6,183,237,238,56,107,251,90,137,159,165,174,159,36,17,\n            124,75,31,230,73,40,102,81,236,228,91,61,194,0,124,184,161,99,191,5,152,218,\n            72,54,28,85,211,154,105,22,63,168,253,36,207,95,131,101,93,35,220,163,173,\n            150,28,98,243,86,32,133,82,187,158,213,41,7,112,150,150,109,103,12,53,78,74,\n            188,152,4,241,116,108,8,202,35,115,39,255,255,255,255,255,255,255,255\n        ]),\n        generator: new Uint8Array([2]),\n        public: publicKey, //a DH public key from generateKey or importKey\n    },\n    privateKey, //your DH private key from generateKey or importKey\n    256 //the number of bits you want to derive\n)\n.then(function(bits){\n    //returns the derived bits as an ArrayBuffer\n    console.log(new Uint8Array(bits));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## SHA\n#### SHA-1 - digest\n```javascript\nwindow.crypto.subtle.digest(\n    {\n        name: \"SHA-1\",\n    },\n    new Uint8Array([1,2,3,4]) //The data you want to hash as an ArrayBuffer\n)\n.then(function(hash){\n    //returns the hash as an ArrayBuffer\n    console.log(new Uint8Array(hash));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n#### SHA-256 - digest\n```javascript\nwindow.crypto.subtle.digest(\n    {\n        name: \"SHA-256\",\n    },\n    new Uint8Array([1,2,3,4]) //The data you want to hash as an ArrayBuffer\n)\n.then(function(hash){\n    //returns the hash as an ArrayBuffer\n    console.log(new Uint8Array(hash));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n#### SHA-384 - digest\n```javascript\nwindow.crypto.subtle.digest(\n    {\n        name: \"SHA-384\",\n    },\n    new Uint8Array([1,2,3,4]) //The data you want to hash as an ArrayBuffer\n)\n.then(function(hash){\n    //returns the hash as an ArrayBuffer\n    console.log(new Uint8Array(hash));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n#### SHA-512 - digest\n```javascript\nwindow.crypto.subtle.digest(\n    {\n        name: \"SHA-512\",\n    },\n    new Uint8Array([1,2,3,4]) //The data you want to hash as an ArrayBuffer\n)\n.then(function(hash){\n    //returns the hash as an ArrayBuffer\n    console.log(new Uint8Array(hash));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## CONCAT\n#### CONCAT - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"raw\", //only \"raw\" is allowed\n    keydata, //your raw key data as an ArrayBuffer\n    {\n        name: \"CONCAT\",\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"deriveKey\", \"deriveBits\"] //can be any combination of \"deriveKey\" and \"deriveBits\"\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### CONCAT - deriveKey\n```javascript\nwindow.crypto.subtle.deriveKey(\n    {\n        \"name\": \"CONCAT\",\n        algorithmId: ArrayBuffer, //?????? I don't know what this should be\n        partyUInfo: ArrayBuffer, //?????? I don't know what this should be\n        partyVInfo: ArrayBuffer, //?????? I don't know what this should be\n        publicInfo: ArrayBuffer, //?????? I don't know what this should be\n        privateInfo: ArrayBuffer, //?????? I don't know what this should be\n        hash: {name: \"SHA-1\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n    },\n    key, //your key from importKey\n    { //the key type you want to create based on the derived bits\n        name: \"AES-CTR\", //can be any AES algorithm (\"AES-CTR\", \"AES-CBC\", \"AES-CMAC\", \"AES-GCM\", \"AES-CFB\", \"AES-KW\", \"ECDH\", \"DH\", or \"HMAC\")\n        //the generateKey parameters for that type of algorithm\n        length: 256, //can be  128, 192, or 256\n    },\n    false, //whether the derived key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //limited to the options in that algorithm's importKey\n)\n.then(function(key){\n    //returns the derived key\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### CONCAT - deriveBits\n```javascript\nwindow.crypto.subtle.deriveBits(\n    {\n        \"name\": \"CONCAT\",\n        algorithmId: ArrayBuffer, //?????? I don't know what this should be\n        partyUInfo: ArrayBuffer, //?????? I don't know what this should be\n        partyVInfo: ArrayBuffer, //?????? I don't know what this should be\n        publicInfo: ArrayBuffer, //?????? I don't know what this should be\n        privateInfo: ArrayBuffer, //?????? I don't know what this should be\n        hash: {name: \"SHA-1\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n    },\n    key, //your key importKey\n    256 //the number of bits you want to derive\n)\n.then(function(bits){\n    //returns the derived bits as an ArrayBuffer\n    console.log(new Uint8Array(bits));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## HKDF-CTR\n#### HKDF-CTR - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"raw\", //only \"raw\" is allowed\n    keydata, //your raw key data as an ArrayBuffer\n    {\n        name: \"HKDF-CTR\",\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"deriveKey\", \"deriveBits\"] //can be any combination of \"deriveKey\" and \"deriveBits\"\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### HKDF-CTR - deriveKey\n```javascript\nwindow.crypto.subtle.deriveKey(\n    {\n        \"name\": \"HKDF-CTR\",\n        label: ArrayBuffer, //?????? I don't know what this should be\n        context: ArrayBuffer, //?????? I don't know what this should be\n        hash: {name: \"SHA-1\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n    },\n    key, //your key from importKey\n    { //the key type you want to create based on the derived bits\n        name: \"AES-CTR\", //can be any AES algorithm (\"AES-CTR\", \"AES-CBC\", \"AES-CMAC\", \"AES-GCM\", \"AES-CFB\", \"AES-KW\", \"ECDH\", \"DH\", or \"HMAC\")\n        //the generateKey parameters for that type of algorithm\n        length: 256, //can be  128, 192, or 256\n    },\n    false, //whether the derived key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //limited to the options in that algorithm's importKey\n)\n.then(function(key){\n    //returns the derived key\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### HKDF-CTR - deriveBits\n```javascript\nwindow.crypto.subtle.deriveBits(\n    {\n        \"name\": \"HKDF-CTR\",\n        label: ArrayBuffer, //?????? I don't know what this should be\n        context: ArrayBuffer, //?????? I don't know what this should be\n        hash: {name: \"SHA-1\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n    },\n    key, //your key importKey\n    256 //the number of bits you want to derive\n)\n.then(function(bits){\n    //returns the derived bits as an ArrayBuffer\n    console.log(new Uint8Array(bits));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n\n## PBKDF2\n#### PBKDF2 - generateKey\n```javascript\n//NOTE: This prompts the user to enter a password.\nwindow.crypto.subtle.generateKey(\n    {\n        name: \"PBKDF2\",\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"deriveKey\", \"deriveBits\"] //can be any combination of \"deriveKey\" and \"deriveBits\"\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### PBKDF2 - importKey\n```javascript\nwindow.crypto.subtle.importKey(\n    \"raw\", //only \"raw\" is allowed\n    window.crypto.getRandomValues(new Uint8Array(16)), //your password\n    {\n        name: \"PBKDF2\",\n    },\n    false, //whether the key is extractable (i.e. can be used in exportKey)\n    [\"deriveKey\", \"deriveBits\"] //can be any combination of \"deriveKey\" and \"deriveBits\"\n)\n.then(function(key){\n    //returns a key object\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### PBKDF2 - deriveKey\n```javascript\nwindow.crypto.subtle.deriveKey(\n    {\n        \"name\": \"PBKDF2\",\n        salt: window.crypto.getRandomValues(new Uint8Array(16)),\n        iterations: 1000,\n        hash: {name: \"SHA-1\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n    },\n    key, //your key from generateKey or importKey\n    { //the key type you want to create based on the derived bits\n        name: \"AES-CTR\", //can be any AES algorithm (\"AES-CTR\", \"AES-CBC\", \"AES-CMAC\", \"AES-GCM\", \"AES-CFB\", \"AES-KW\", \"ECDH\", \"DH\", or \"HMAC\")\n        //the generateKey parameters for that type of algorithm\n        length: 256, //can be  128, 192, or 256\n    },\n    false, //whether the derived key is extractable (i.e. can be used in exportKey)\n    [\"encrypt\", \"decrypt\"] //limited to the options in that algorithm's importKey\n)\n.then(function(key){\n    //returns the derived key\n    console.log(key);\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n#### PBKDF2 - deriveBits\n```javascript\nwindow.crypto.subtle.deriveBits(\n    {\n        \"name\": \"PBKDF2\",\n        salt: window.crypto.getRandomValues(new Uint8Array(16)),\n        iterations: 1000,\n        hash: {name: \"SHA-1\"}, //can be \"SHA-1\", \"SHA-256\", \"SHA-384\", or \"SHA-512\"\n    },\n    key, //your key from generateKey or importKey\n    256 //the number of bits you want to derive\n)\n.then(function(bits){\n    //returns the derived bits as an ArrayBuffer\n    console.log(new Uint8Array(bits));\n})\n.catch(function(err){\n    console.error(err);\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/diafygi.github.io%2Fwebcrypto-examples%2F","html_url":"https://awesome.ecosyste.ms/projects/diafygi.github.io%2Fwebcrypto-examples%2F","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/diafygi.github.io%2Fwebcrypto-examples%2F/lists"}