# Web5 JS Key Management

:::info
:information_source: **Info**
All of the following are written with the _**SDK developer experience**_ in mind becase
it isn't intended nor expected for an app developer who is building DWAs on the Web5
platform abstraction to be directly interacting with `KeyManager` or `KeyManagementSystem`
implementations directly.
:::
## Use Case DevEx (Single KMS)
:::info
:notebook: **Note** --- Describes the most simplistic case when there is a single KMS. As a result, the `kms` property can be omitted in method options because `KeyManager` will automatically use the only KMS that is registered.
:::
### `secp256k1`
#### Create a key pair
Creates an `secp256k1` key pair using the. The spec `secp256k1` is an alias for ECDSA using the secp256k1 curve and SHA-256.
```typescript
const keyPair = await agent.keyManager.createKey({
spec: 'secp256k1',
usages : ['sign', 'verify']
});
/*
// Detail of the key pair that this operation creates:
{
"privateKey": {
"id": "559f3ee2-4f0a-4028-80b5-bea0b6e7e4af",
"algorithm": {
"name": "ECDSA",
"namedCurve": "K-256"
},
"spec": "ECDSA_K-256",
"state": "Enabled",
"type": "private",
"usages": [
"sign"
]
},
"publicKey": {
"id": "559f3ee2-4f0a-4028-80b5-bea0b6e7e4af",
"algorithm": {
"name": "ECDSA",
"namedCurve": "K-256"
},
"material": ArrayBuffer(33),
"spec": "ECDSA_K-256",
"state": "Enabled",
"type": "public",
"usages": [
"verify"
]
}
}
*/
```
#### Sign Data
Data can be signed by referencing a key by `id` or `alias` property, or by passing in the CryptoKey object directly. The latter mimics the interface for the W3C WebCrypto API.
```typescript
// Define and encode the message to be signed.
const message = `Are You There Bob? It's Me, Alice.`;
const encodedMessage = new TextEncoder().encode(message);
```
By passing an alias that is a `kid` from a DID document:
```typescript
const signature = await agent.keyManager.sign({
keyRef: 'did:ion:EiClkZMDxPKqC9c-umQfTkR8vvZ9JPhl_xLDI9Nfk38w5w#authz',
data: encodedMessage,
signerOptions: { hash: 'SHA-256' }
})
```
--OR--
Using a CryptoKey instance:
```typescript
// Signing operation
const signature = await agent.keyManager.verify({
key: keyPair.publicKey,
data: encodedMessage,
signerOptions: { hash: 'SHA-256' }
});
```
#### Verify Signed Data
By passing an alias that is a `kid` from a DID document:
```typescript
const signature = await agent.keyManager.sign({
keyRef: 'did:ion:EiClkZMDxPKqC9c-umQfTkR8vvZ9JPhl_xLDI9Nfk38w5w#authz',
signature: signature,
data: encodedMessage,
signerOptions: { hash: 'SHA-256' }
})
```
--OR--
Using a CryptoKey instance:
```typescript
// Signing operation
const signature = await agent.keyManager.sign({
key: keyPair.privateKey,
signature: signature,
data: encodedMessage,
verifierOptions: { hash: 'SHA-256' }
});
```
#### Derive a Symmetric Key to Encrypt Messages
In this example Alice and Bob each generate an ECDH key pair, then exchange public keys. They then use deriveKey() to derive a shared AES key, that they could use to encrypt messages.
A more likely scenario in the context of using DIDs is that the `secp256k1` public keys of both Alice and Bob would already be published in their DID documents. Each party would obtain the public key of the other after resolving their DID document.
```typescript
const alicesKeyPair = await agent.keyManager.createKey({
spec : 'ECDH_K-256',
usages : ['deriveKey']
});
const bobsKeyPair = await agent.keyManager.createKey({
spec : 'ECDH_K-256',
usages : ['deriveKey']
})
return window.crypto.subtle.deriveKey(
{
name: "ECDH",
public: publicKey,
},
privateKey,
{
name: "AES-GCM",
length: 256,
},
false,
["encrypt", "decrypt"]
);
```
## `KeyManager` DevEx
### Default Algorithms
| Spec Name | Crypto Primitive | Algorithm Description | Aliases |
| --- | --- | --- | --- |
| `AES-GCM_256` | AES | AES GCM using 256-bit key | `A256GCM` |
| `ECDSA_K-256` | ECC | ECDSA using secp256k1 curve and SHA-256 | `ES256K`, `secp256k1` |
| `EdDSA_Ed25519` | ECC | EdDSA using Ed25519 curve | `Ed25519` |
| `HMAC_SHA256` | HMAC | HMAC with a SHA-256 digest | `HS256` |
**Typical Usage**

## Open Questions
---
### Should the `KeyManager` and `KeyManagementSystem` interfaces be modeled as a request/response API?
In other words, rather than
```typescript
async createKey(options: KeyManagerCreateOptions): Promise<ManagedKey | ManagedKeyPair>
```
```typescript
async createKey(request: KeyManagerCreateRequest): Promise<ManagedKey | ManagedKeyPair>
```
AWS API
```javascript
var params = {
KeyId: "1234abcd-12ab-34cd-56ef-1234567890ab"// An identifier for the KMS key. You can use the key ID, key ARN, alias name, alias ARN of the KMS key.
};
kms.describeKey(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
/*
data = {
KeyMetadata: {
AWSAccountId: "111122223333",
Arn: "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab",
CreationDate: <Date Representation>,
CustomerMasterKeySpec: "RSA_2048",
Description: "",
Enabled: false,
KeyId: "1234abcd-12ab-34cd-56ef-1234567890ab",
KeyManager: "CUSTOMER",
KeySpec: "RSA_2048",
KeyState: "Disabled",
KeyUsage: "SIGN_VERIFY",
MultiRegion: false,
Origin: "AWS_KMS",
SigningAlgorithms: [
"RSASSA_PKCS1_V1_5_SHA_256",
"RSASSA_PKCS1_V1_5_SHA_384",
"RSASSA_PKCS1_V1_5_SHA_512",
"RSASSA_PSS_SHA_256",
"RSASSA_PSS_SHA_384",
"RSASSA_PSS_SHA_512"
]
}
}
*/
});
```
GCP API
```javascript
const {KeyManagementServiceClient} = require('@google-cloud/kms').v1;
// Instantiates a client
const kmsClient = new KeyManagementServiceClient();
// Construct request
const request = {
name,
};
// Run request
const response = await kmsClient.getCryptoKey(request);
console.log(response);
```
# Convo
# Web Cryptography API Examples
## RSASSA-PKCS1-v1_5
#### RSASSA-PKCS1-v1_5 - generateKey
```javascript
window.crypto.subtle.generateKey(
{
name: "RSASSA-PKCS1-v1_5",
modulusLength: 2048, //can be 1024, 2048, or 4096
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["sign", "verify"] //can be any combination of "sign" and "verify"
)
.then(function(key){
//returns a keypair object
console.log(key);
console.log(key.publicKey);
console.log(key.privateKey);
})
.catch(function(err){
console.error(err);
});
```
#### RSASSA-PKCS1-v1_5 - importKey
```javascript
window.crypto.subtle.importKey(
"jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
{ //this is an example jwk key, other key types are Uint8Array objects
kty: "RSA",
e: "AQAB",
n: "vGO3eU16ag9zRkJ4AK8ZUZrjbtp5xWK0LyFMNT8933evJoHeczexMUzSiXaLrEFSyQZortk81zJH3y41MBO_UFDO_X0crAquNrkjZDrf9Scc5-MdxlWU2Jl7Gc4Z18AC9aNibWVmXhgvHYkEoFdLCFG-2Sq-qIyW4KFkjan05IE",
alg: "RS256",
ext: true,
},
{ //these are the algorithm options
name: "RSASSA-PKCS1-v1_5",
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["verify"] //"verify" for public key import, "sign" for private key imports
)
.then(function(publicKey){
//returns a publicKey (or privateKey if you are importing a private key)
console.log(publicKey);
})
.catch(function(err){
console.error(err);
});
```
#### RSASSA-PKCS1-v1_5 - exportKey
```javascript
window.crypto.subtle.exportKey(
"jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
publicKey //can be a publicKey or privateKey, as long as extractable was true
)
.then(function(keydata){
//returns the exported key data
console.log(keydata);
})
.catch(function(err){
console.error(err);
});
```
#### RSASSA-PKCS1-v1_5 - sign
```javascript
window.crypto.subtle.sign(
{
name: "RSASSA-PKCS1-v1_5",
},
privateKey, //from generateKey or importKey above
data //ArrayBuffer of data you want to sign
)
.then(function(signature){
//returns an ArrayBuffer containing the signature
console.log(new Uint8Array(signature));
})
.catch(function(err){
console.error(err);
});
```
#### RSASSA-PKCS1-v1_5 - verify
```javascript
window.crypto.subtle.verify(
{
name: "RSASSA-PKCS1-v1_5",
},
publicKey, //from generateKey or importKey above
signature, //ArrayBuffer of the signature
data //ArrayBuffer of the data
)
.then(function(isvalid){
//returns a boolean on whether the signature is true or not
console.log(isvalid);
})
.catch(function(err){
console.error(err);
});
```
## RSA-PSS
#### RSA-PSS - generateKey
```javascript
window.crypto.subtle.generateKey(
{
name: "RSA-PSS",
modulusLength: 2048, //can be 1024, 2048, or 4096
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["sign", "verify"] //can be any combination of "sign" and "verify"
)
.then(function(key){
//returns a keypair object
console.log(key);
console.log(key.publicKey);
console.log(key.privateKey);
})
.catch(function(err){
console.error(err);
});
```
#### RSA-PSS - importKey
```javascript
window.crypto.subtle.importKey(
"jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
{ //this is an example jwk key, other key types are Uint8Array objects
kty: "RSA",
e: "AQAB",
n: "vGO3eU16ag9zRkJ4AK8ZUZrjbtp5xWK0LyFMNT8933evJoHeczexMUzSiXaLrEFSyQZortk81zJH3y41MBO_UFDO_X0crAquNrkjZDrf9Scc5-MdxlWU2Jl7Gc4Z18AC9aNibWVmXhgvHYkEoFdLCFG-2Sq-qIyW4KFkjan05IE",
alg: "PS256",
ext: true,
},
{ //these are the algorithm options
name: "RSA-PSS",
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["verify"] //"verify" for public key import, "sign" for private key imports
)
.then(function(publicKey){
//returns a publicKey (or privateKey if you are importing a private key)
console.log(publicKey);
})
.catch(function(err){
console.error(err);
});
```
#### RSA-PSS - exportKey
```javascript
window.crypto.subtle.exportKey(
"jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
publicKey //can be a publicKey or privateKey, as long as extractable was true
)
.then(function(keydata){
//returns the exported key data
console.log(keydata);
})
.catch(function(err){
console.error(err);
});
```
#### RSA-PSS - sign
```javascript
window.crypto.subtle.sign(
{
name: "RSA-PSS",
saltLength: 128, //the length of the salt
},
privateKey, //from generateKey or importKey above
data //ArrayBuffer of data you want to sign
)
.then(function(signature){
//returns an ArrayBuffer containing the signature
console.log(new Uint8Array(signature));
})
.catch(function(err){
console.error(err);
});
```
#### RSA-PSS - verify
```javascript
window.crypto.subtle.verify(
{
name: "RSA-PSS",
saltLength: 128, //the length of the salt
},
publicKey, //from generateKey or importKey above
signature, //ArrayBuffer of the signature
data //ArrayBuffer of the data
)
.then(function(isvalid){
//returns a boolean on whether the signature is true or not
console.log(isvalid);
})
.catch(function(err){
console.error(err);
});
```
## RSA-OAEP
#### RSA-OAEP - generateKey
```javascript
window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 2048, //can be 1024, 2048, or 4096
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
)
.then(function(key){
//returns a keypair object
console.log(key);
console.log(key.publicKey);
console.log(key.privateKey);
})
.catch(function(err){
console.error(err);
});
```
#### RSA-OAEP - importKey
```javascript
window.crypto.subtle.importKey(
"jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
{ //this is an example jwk key, other key types are Uint8Array objects
kty: "RSA",
e: "AQAB",
n: "vGO3eU16ag9zRkJ4AK8ZUZrjbtp5xWK0LyFMNT8933evJoHeczexMUzSiXaLrEFSyQZortk81zJH3y41MBO_UFDO_X0crAquNrkjZDrf9Scc5-MdxlWU2Jl7Gc4Z18AC9aNibWVmXhgvHYkEoFdLCFG-2Sq-qIyW4KFkjan05IE",
alg: "RSA-OAEP-256",
ext: true,
},
{ //these are the algorithm options
name: "RSA-OAEP",
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt"] //"encrypt" or "wrapKey" for public key import or
//"decrypt" or "unwrapKey" for private key imports
)
.then(function(publicKey){
//returns a publicKey (or privateKey if you are importing a private key)
console.log(publicKey);
})
.catch(function(err){
console.error(err);
});
```
#### RSA-OAEP - exportKey
```javascript
window.crypto.subtle.exportKey(
"jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
publicKey //can be a publicKey or privateKey, as long as extractable was true
)
.then(function(keydata){
//returns the exported key data
console.log(keydata);
})
.catch(function(err){
console.error(err);
});
```
#### RSA-OAEP - encrypt
```javascript
window.crypto.subtle.encrypt(
{
name: "RSA-OAEP",
//label: Uint8Array([...]) //optional
},
publicKey, //from generateKey or importKey above
data //ArrayBuffer of data you want to encrypt
)
.then(function(encrypted){
//returns an ArrayBuffer containing the encrypted data
console.log(new Uint8Array(encrypted));
})
.catch(function(err){
console.error(err);
});
```
#### RSA-OAEP - decrypt
```javascript
window.crypto.subtle.decrypt(
{
name: "RSA-OAEP",
//label: Uint8Array([...]) //optional
},
privateKey, //from generateKey or importKey above
data //ArrayBuffer of the data
)
.then(function(decrypted){
//returns an ArrayBuffer containing the decrypted data
console.log(new Uint8Array(decrypted));
})
.catch(function(err){
console.error(err);
});
```
#### RSA-OAEP - wrapKey
```javascript
window.crypto.subtle.wrapKey(
"raw", //the export format, must be "raw" (only available sometimes)
key, //the key you want to wrap, must be able to fit in RSA-OAEP padding
publicKey, //the public key with "wrapKey" usage flag
{ //these are the wrapping key's algorithm options
name: "RSA-OAEP",
hash: {name: "SHA-256"},
}
)
.then(function(wrapped){
//returns an ArrayBuffer containing the encrypted data
console.log(new Uint8Array(wrapped));
})
.catch(function(err){
console.error(err);
});
```
#### RSA-OAEP - unwrapKey
```javascript
window.crypto.subtle.unwrapKey(
"raw", //the import format, must be "raw" (only available sometimes)
wrapped, //the key you want to unwrap
privateKey, //the private key with "unwrapKey" usage flag
{ //these are the wrapping key's algorithm options
name: "RSA-OAEP",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {name: "SHA-256"},
},
{ //this what you want the wrapped key to become (same as when wrapping)
name: "AES-GCM",
length: 256
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //the usages you want the unwrapped key to have
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
## ECDSA
#### ECDSA - generateKey
```javascript
window.crypto.subtle.generateKey(
{
name: "ECDSA",
namedCurve: "P-256", //can be "P-256", "P-384", or "P-521"
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["sign", "verify"] //can be any combination of "sign" and "verify"
)
.then(function(key){
//returns a keypair object
console.log(key);
console.log(key.publicKey);
console.log(key.privateKey);
})
.catch(function(err){
console.error(err);
});
```
#### ECDSA - importKey
```javascript
window.crypto.subtle.importKey(
"jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
{ //this is an example jwk key, other key types are Uint8Array objects
kty: "EC",
crv: "P-256",
x: "zCQ5BPHPCLZYgdpo1n-x_90P2Ij52d53YVwTh3ZdiMo",
y: "pDfQTUx0-OiZc5ZuKMcA7v2Q7ZPKsQwzB58bft0JTko",
ext: true,
},
{ //these are the algorithm options
name: "ECDSA",
namedCurve: "P-256", //can be "P-256", "P-384", or "P-521"
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["verify"] //"verify" for public key import, "sign" for private key imports
)
.then(function(publicKey){
//returns a publicKey (or privateKey if you are importing a private key)
console.log(publicKey);
})
.catch(function(err){
console.error(err);
});
```
#### ECDSA - exportKey
```javascript
window.crypto.subtle.exportKey(
"jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
publicKey //can be a publicKey or privateKey, as long as extractable was true
)
.then(function(keydata){
//returns the exported key data
console.log(keydata);
})
.catch(function(err){
console.error(err);
});
```
#### ECDSA - sign
```javascript
window.crypto.subtle.sign(
{
name: "ECDSA",
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
privateKey, //from generateKey or importKey above
data //ArrayBuffer of data you want to sign
)
.then(function(signature){
//returns an ArrayBuffer containing the signature
console.log(new Uint8Array(signature));
})
.catch(function(err){
console.error(err);
});
```
#### ECDSA - verify
```javascript
window.crypto.subtle.verify(
{
name: "ECDSA",
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
publicKey, //from generateKey or importKey above
signature, //ArrayBuffer of the signature
data //ArrayBuffer of the data
)
.then(function(isvalid){
//returns a boolean on whether the signature is true or not
console.log(isvalid);
})
.catch(function(err){
console.error(err);
});
```
## ECDH
#### ECDH - generateKey
```javascript
window.crypto.subtle.generateKey(
{
name: "ECDH",
namedCurve: "P-256", //can be "P-256", "P-384", or "P-521"
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["deriveKey", "deriveBits"] //can be any combination of "deriveKey" and "deriveBits"
)
.then(function(key){
//returns a keypair object
console.log(key);
console.log(key.publicKey);
console.log(key.privateKey);
})
.catch(function(err){
console.error(err);
});
```
#### ECDH - importKey
```javascript
window.crypto.subtle.importKey(
"jwk", //can be "jwk" (public or private), "raw" (public only), "spki" (public only), or "pkcs8" (private only)
{ //this is an example jwk key, other key types are Uint8Array objects
kty: "EC",
crv: "P-256",
x: "kgR_PqO07L8sZOBbw6rvv7O_f7clqDeiE3WnMkb5EoI",
y: "djI-XqCqSyO9GFk_QT_stROMCAROIvU8KOORBgQUemE",
d: "5aPFSt0UFVXYGu-ZKyC9FQIUOAMmnjzdIwkxCMe3Iok",
ext: true,
},
{ //these are the algorithm options
name: "ECDH",
namedCurve: "P-256", //can be "P-256", "P-384", or "P-521"
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["deriveKey", "deriveBits"] //"deriveKey" and/or "deriveBits" for private keys only (just put an empty list if importing a public key)
)
.then(function(privateKey){
//returns a privateKey (or publicKey if you are importing a public key)
console.log(privateKey);
})
.catch(function(err){
console.error(err);
});
```
#### ECDH - exportKey
```javascript
window.crypto.subtle.exportKey(
"jwk", //can be "jwk" (public or private), "raw" (public only), "spki" (public only), or "pkcs8" (private only)
publicKey //can be a publicKey or privateKey, as long as extractable was true
)
.then(function(keydata){
//returns the exported key data
console.log(keydata);
})
.catch(function(err){
console.error(err);
});
```
#### ECDH - deriveKey
```javascript
window.crypto.subtle.deriveKey(
{
name: "ECDH",
namedCurve: "P-256", //can be "P-256", "P-384", or "P-521"
public: publicKey, //an ECDH public key from generateKey or importKey
},
privateKey, //your ECDH private key from generateKey or importKey
{ //the key type you want to create based on the derived bits
name: "AES-CTR", //can be any AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH", or "HMAC")
//the generateKey parameters for that type of algorithm
length: 256, //can be 128, 192, or 256
},
false, //whether the derived key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //limited to the options in that algorithm's importKey
)
.then(function(keydata){
//returns the exported key data
console.log(keydata);
})
.catch(function(err){
console.error(err);
});
```
#### ECDH - deriveBits
```javascript
window.crypto.subtle.deriveBits(
{
name: "ECDH",
namedCurve: "P-256", //can be "P-256", "P-384", or "P-521"
public: publicKey, //an ECDH public key from generateKey or importKey
},
privateKey, //your ECDH private key from generateKey or importKey
256 //the number of bits you want to derive
)
.then(function(bits){
//returns the derived bits as an ArrayBuffer
console.log(new Uint8Array(bits));
})
.catch(function(err){
console.error(err);
});
```
## AES-CTR
#### AES-CTR - generateKey
```javascript
window.crypto.subtle.generateKey(
{
name: "AES-CTR",
length: 256, //can be 128, 192, or 256
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //can "encrypt", "decrypt", "wrapKey", or "unwrapKey"
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### AES-CTR - importKey
```javascript
window.crypto.subtle.importKey(
"jwk", //can be "jwk" or "raw"
{ //this is an example jwk key, "raw" would be an ArrayBuffer
kty: "oct",
k: "Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE",
alg: "A256CTR",
ext: true,
},
{ //this is the algorithm options
name: "AES-CTR",
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //can "encrypt", "decrypt", "wrapKey", or "unwrapKey"
)
.then(function(key){
//returns the symmetric key
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### AES-CTR - exportKey
```javascript
window.crypto.subtle.exportKey(
"jwk", //can be "jwk" or "raw"
key //extractable must be true
)
.then(function(keydata){
//returns the exported key data
console.log(keydata);
})
.catch(function(err){
console.error(err);
});
```
#### AES-CTR - encrypt
```javascript
window.crypto.subtle.encrypt(
{
name: "AES-CTR",
//Don't re-use counters!
//Always use a new counter every time your encrypt!
counter: new Uint8Array(16),
length: 128, //can be 1-128
},
key, //from generateKey or importKey above
data //ArrayBuffer of data you want to encrypt
)
.then(function(encrypted){
//returns an ArrayBuffer containing the encrypted data
console.log(new Uint8Array(encrypted));
})
.catch(function(err){
console.error(err);
});
```
#### AES-CTR - decrypt
```javascript
window.crypto.subtle.decrypt(
{
name: "AES-CTR",
counter: ArrayBuffer(16), //The same counter you used to encrypt
length: 128, //The same length you used to encrypt
},
key, //from generateKey or importKey above
data //ArrayBuffer of the data
)
.then(function(decrypted){
//returns an ArrayBuffer containing the decrypted data
console.log(new Uint8Array(decrypted));
})
.catch(function(err){
console.error(err);
});
```
#### AES-CTR - wrapKey
```javascript
window.crypto.subtle.wrapKey(
"jwk", //can be "jwk", "raw", "spki", or "pkcs8"
key, //the key you want to wrap, must be able to export to "raw" format
wrappingKey, //the AES-CTR key with "wrapKey" usage flag
{ //these are the wrapping key's algorithm options
name: "AES-CTR",
//Don't re-use counters!
//Always use a new counter every time your encrypt!
counter: new Uint8Array(16),
length: 128, //can be 1-128
}
)
.then(function(wrapped){
//returns an ArrayBuffer containing the encrypted data
console.log(new Uint8Array(wrapped));
})
.catch(function(err){
console.error(err);
});
```
#### AES-CTR - unwrapKey
```javascript
window.crypto.subtle.unwrapKey(
"jwk", //"jwk", "raw", "spki", or "pkcs8" (whatever was used in wrapping)
wrapped, //the key you want to unwrap
wrappingKey, //the AES-CTR key with "unwrapKey" usage flag
{ //these are the wrapping key's algorithm options
name: "AES-CTR",
//Don't re-use counters!
//Always use a new counter every time your encrypt!
counter: new Uint8Array(16),
length: 128, //can be 1-128
},
{ //this what you want the wrapped key to become (same as when wrapping)
name: "AES-GCM",
length: 256
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //the usages you want the unwrapped key to have
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
## AES-CBC
#### AES-CBC - generateKey
```javascript
window.crypto.subtle.generateKey(
{
name: "AES-CBC",
length: 256, //can be 128, 192, or 256
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //can be "encrypt", "decrypt", "wrapKey", or "unwrapKey"
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### AES-CBC - importKey
```javascript
window.crypto.subtle.importKey(
"jwk", //can be "jwk" or "raw"
{ //this is an example jwk key, "raw" would be an ArrayBuffer
kty: "oct",
k: "Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE",
alg: "A256CBC",
ext: true,
},
{ //this is the algorithm options
name: "AES-CBC",
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //can be "encrypt", "decrypt", "wrapKey", or "unwrapKey"
)
.then(function(key){
//returns the symmetric key
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### AES-CBC - exportKey
```javascript
window.crypto.subtle.exportKey(
"jwk", //can be "jwk" or "raw"
key //extractable must be true
)
.then(function(keydata){
//returns the exported key data
console.log(keydata);
})
.catch(function(err){
console.error(err);
});
```
#### AES-CBC - encrypt
```javascript
window.crypto.subtle.encrypt(
{
name: "AES-CBC",
//Don't re-use initialization vectors!
//Always generate a new iv every time your encrypt!
iv: window.crypto.getRandomValues(new Uint8Array(16)),
},
key, //from generateKey or importKey above
data //ArrayBuffer of data you want to encrypt
)
.then(function(encrypted){
//returns an ArrayBuffer containing the encrypted data
console.log(new Uint8Array(encrypted));
})
.catch(function(err){
console.error(err);
});
```
#### AES-CBC - decrypt
```javascript
window.crypto.subtle.decrypt(
{
name: "AES-CBC",
iv: ArrayBuffer(16), //The initialization vector you used to encrypt
},
key, //from generateKey or importKey above
data //ArrayBuffer of the data
)
.then(function(decrypted){
//returns an ArrayBuffer containing the decrypted data
console.log(new Uint8Array(decrypted));
})
.catch(function(err){
console.error(err);
});
```
#### AES-CBC - wrapKey
```javascript
window.crypto.subtle.wrapKey(
"jwk", //can be "jwk", "raw", "spki", or "pkcs8"
key, //the key you want to wrap, must be able to export to above format
wrappingKey, //the AES-CBC key with "wrapKey" usage flag
{ //these are the wrapping key's algorithm options
name: "AES-CBC",
//Don't re-use initialization vectors!
//Always generate a new iv every time your encrypt!
iv: window.crypto.getRandomValues(new Uint8Array(16)),
}
)
.then(function(wrapped){
//returns an ArrayBuffer containing the encrypted data
console.log(new Uint8Array(wrapped));
})
.catch(function(err){
console.error(err);
});
```
#### AES-CBC - unwrapKey
```javascript
window.crypto.subtle.unwrapKey(
"jwk", //"jwk", "raw", "spki", or "pkcs8" (whatever was used in wrapping)
wrapped, //the key you want to unwrap
wrappingKey, //the AES-CBC key with "unwrapKey" usage flag
{ //these are the wrapping key's algorithm options
name: "AES-CBC",
iv: ArrayBuffer(16), //The initialization vector you used to encrypt
},
{ //this what you want the wrapped key to become (same as when wrapping)
name: "AES-GCM",
length: 256
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //the usages you want the unwrapped key to have
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
## AES-CMAC
#### AES-CMAC - generateKey
```javascript
window.crypto.subtle.generateKey(
{
name: "AES-CMAC",
length: 256, //can be 128, 192, or 256
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["sign", "verify"] //can be any combination of "sign" and "verify"
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### AES-CMAC - importKey
```javascript
window.crypto.subtle.importKey(
"jwk", //can be "jwk" or "raw"
{ //this is an example jwk key, "raw" would be an ArrayBuffer
kty: "oct",
k: "Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE",
alg: "A256CMAC",
ext: true,
},
{ //this is the algorithm options
name: "AES-CMAC",
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["sign", "verify"] //can be any combination of "sign" and "verify"
)
.then(function(key){
//returns the symmetric key
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### AES-CMAC - exportKey
```javascript
window.crypto.subtle.exportKey(
"jwk", //can be "jwk" or "raw"
key //extractable must be true
)
.then(function(keydata){
//returns the exported key data
console.log(keydata);
})
.catch(function(err){
console.error(err);
});
```
#### AES-CMAC - sign
```javascript
window.crypto.subtle.sign(
{
name: "AES-CMAC",
length: 256, //bit length of the MAC
},
key, //from generateKey or importKey above
data //ArrayBuffer of data you want to sign
)
.then(function(signature){
//returns an ArrayBuffer containing the signature
console.log(new Uint8Array(signature));
})
.catch(function(err){
console.error(err);
});
```
#### AES-CMAC - verify
```javascript
window.crypto.subtle.verify(
{
name: "AES-CMAC",
length: 256, //bit length of the MAC
},
key, //from generateKey or importKey above
signature, //ArrayBuffer of the signature
data //ArrayBuffer of the data
)
.then(function(isvalid){
//returns a boolean on whether the signature is true or not
console.log(isvalid);
})
.catch(function(err){
console.error(err);
});
```
## AES-GCM
#### AES-GCM - generateKey
```javascript
window.crypto.subtle.generateKey(
{
name: "AES-GCM",
length: 256, //can be 128, 192, or 256
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //can "encrypt", "decrypt", "wrapKey", or "unwrapKey"
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### AES-GCM - importKey
```javascript
window.crypto.subtle.importKey(
"jwk", //can be "jwk" or "raw"
{ //this is an example jwk key, "raw" would be an ArrayBuffer
kty: "oct",
k: "Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE",
alg: "A256GCM",
ext: true,
},
{ //this is the algorithm options
name: "AES-GCM",
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //can "encrypt", "decrypt", "wrapKey", or "unwrapKey"
)
.then(function(key){
//returns the symmetric key
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### AES-GCM - exportKey
```javascript
window.crypto.subtle.exportKey(
"jwk", //can be "jwk" or "raw"
key //extractable must be true
)
.then(function(keydata){
//returns the exported key data
console.log(keydata);
})
.catch(function(err){
console.error(err);
});
```
#### AES-GCM - encrypt
```javascript
window.crypto.subtle.encrypt(
{
name: "AES-GCM",
//Don't re-use initialization vectors!
//Always generate a new iv every time your encrypt!
//Recommended to use 12 bytes length
iv: window.crypto.getRandomValues(new Uint8Array(12)),
//Additional authentication data (optional)
additionalData: ArrayBuffer,
//Tag length (optional)
tagLength: 128, //can be 32, 64, 96, 104, 112, 120 or 128 (default)
},
key, //from generateKey or importKey above
data //ArrayBuffer of data you want to encrypt
)
.then(function(encrypted){
//returns an ArrayBuffer containing the encrypted data
console.log(new Uint8Array(encrypted));
})
.catch(function(err){
console.error(err);
});
```
#### AES-GCM - decrypt
```javascript
window.crypto.subtle.decrypt(
{
name: "AES-GCM",
iv: ArrayBuffer(12), //The initialization vector you used to encrypt
additionalData: ArrayBuffer, //The addtionalData you used to encrypt (if any)
tagLength: 128, //The tagLength you used to encrypt (if any)
},
key, //from generateKey or importKey above
data //ArrayBuffer of the data
)
.then(function(decrypted){
//returns an ArrayBuffer containing the decrypted data
console.log(new Uint8Array(decrypted));
})
.catch(function(err){
console.error(err);
});
```
#### AES-GCM - wrapKey
```javascript
window.crypto.subtle.wrapKey(
"jwk", //can be "jwk", "raw", "spki", or "pkcs8"
key, //the key you want to wrap, must be able to export to above format
wrappingKey, //the AES-GCM key with "wrapKey" usage flag
{ //these are the wrapping key's algorithm options
name: "AES-GCM",
//Don't re-use initialization vectors!
//Always generate a new iv every time your encrypt!
//Recommended to use 12 bytes length
iv: window.crypto.getRandomValues(new Uint8Array(12)),
//Additional authentication data (optional)
additionalData: ArrayBuffer,
//Tag length (optional)
tagLength: 128, //can be 32, 64, 96, 104, 112, 120 or 128 (default)
}
)
.then(function(wrapped){
//returns an ArrayBuffer containing the encrypted data
console.log(new Uint8Array(wrapped));
})
.catch(function(err){
console.error(err);
});
```
#### AES-GCM - unwrapKey
```javascript
window.crypto.subtle.unwrapKey(
"jwk", //"jwk", "raw", "spki", or "pkcs8" (whatever was used in wrapping)
wrapped, //the key you want to unwrap
wrappingKey, //the AES-GCM key with "unwrapKey" usage flag
{ //these are the wrapping key's algorithm options
name: "AES-GCM",
iv: ArrayBuffer(12), //The initialization vector you used to encrypt
additionalData: ArrayBuffer, //The addtionalData you used to encrypt (if any)
tagLength: 128, //The tagLength you used to encrypt (if any)
},
{ //this what you want the wrapped key to become (same as when wrapping)
name: "AES-CBC",
length: 256
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //the usages you want the unwrapped key to have
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
## AES-CFB
#### AES-CFB - generateKey
```javascript
window.crypto.subtle.generateKey(
{
name: "AES-CFB-8",
length: 256, //can be 128, 192, or 256
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //can "encrypt", "decrypt", "wrapKey", or "unwrapKey"
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### AES-CFB - importKey
```javascript
window.crypto.subtle.importKey(
"jwk", //can be "jwk" or "raw"
{ //this is an example jwk key, "raw" would be an ArrayBuffer
kty: "oct",
k: "Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE",
alg: "A256CFB8",
ext: true,
},
{ //this is the algorithm options
name: "AES-CFB-8",
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //can "encrypt", "decrypt", "wrapKey", or "unwrapKey"
)
.then(function(key){
//returns the symmetric key
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### AES-CFB - exportKey
```javascript
window.crypto.subtle.exportKey(
"jwk", //can be "jwk" or "raw"
key //extractable must be true
)
.then(function(keydata){
//returns the exported key data
console.log(keydata);
})
.catch(function(err){
console.error(err);
});
```
#### AES-CFB - encrypt
```javascript
window.crypto.subtle.encrypt(
{
name: "AES-CFB-8",
//Don't re-use initialization vectors!
//Always generate a new iv every time your encrypt!
iv: window.crypto.getRandomValues(new Uint8Array(16)),
},
key, //from generateKey or importKey above
data //ArrayBuffer of data you want to encrypt
)
.then(function(encrypted){
//returns an ArrayBuffer containing the encrypted data
console.log(new Uint8Array(encrypted));
})
.catch(function(err){
console.error(err);
});
```
#### AES-CFB - decrypt
```javascript
window.crypto.subtle.decrypt(
{
name: "AES-CFB-8",
iv: ArrayBuffer(16), //The initialization vector you used to encrypt
},
key, //from generateKey or importKey above
data //ArrayBuffer of the data
)
.then(function(decrypted){
//returns an ArrayBuffer containing the decrypted data
console.log(new Uint8Array(decrypted));
})
.catch(function(err){
console.error(err);
});
```
#### AES-CFB - wrapKey
```javascript
window.crypto.subtle.wrapKey(
"jwk", //can be "jwk", "raw", "spki", or "pkcs8"
key, //the key you want to wrap, must be able to export to above format
wrappingKey, //the AES-CFB key with "wrapKey" usage flag
{ //these are the wrapping key's algorithm options
name: "AES-CFB",
//Don't re-use initialization vectors!
//Always generate a new iv every time your encrypt!
iv: window.crypto.getRandomValues(new Uint8Array(16)),
}
)
.then(function(wrapped){
//returns an ArrayBuffer containing the encrypted data
console.log(new Uint8Array(wrapped));
})
.catch(function(err){
console.error(err);
});
```
#### AES-CFB - unwrapKey
```javascript
window.crypto.subtle.unwrapKey(
"jwk", //"jwk", "raw", "spki", or "pkcs8" (whatever was used in wrapping)
wrapped, //the key you want to unwrap
wrappingKey, //the AES-CFB key with "unwrapKey" usage flag
{ //these are the wrapping key's algorithm options
name: "AES-CFB",
iv: ArrayBuffer(16), //The initialization vector you used to encrypt
},
{ //this what you want the wrapped key to become (same as when wrapping)
name: "AES-GCM",
length: 256
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //the usages you want the unwrapped key to have
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
## AES-KW
#### AES-KW - generateKey
```javascript
window.crypto.subtle.generateKey(
{
name: "AES-KW",
length: 256, //can be 128, 192, or 256
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["wrapKey", "unwrapKey"] //can be any combination of "wrapKey" and "unwrapKey"
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### AES-KW - importKey
```javascript
window.crypto.subtle.importKey(
"jwk", //can be "jwk" or "raw"
{ //this is an example jwk key, "raw" would be an ArrayBuffer
kty: "oct",
k: "Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE",
alg: "A256KW",
ext: true,
},
{ //this is the algorithm options
name: "AES-KW",
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["wrapKey", "unwrapKey"] //can be any combination of "wrapKey" and "unwrapKey"
)
.then(function(key){
//returns the symmetric key
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### AES-KW - exportKey
```javascript
window.crypto.subtle.exportKey(
"jwk", //can be "jwk" or "raw"
key //extractable must be true
)
.then(function(keydata){
//returns the exported key data
console.log(keydata);
})
.catch(function(err){
console.error(err);
});
```
#### AES-KW - wrapKey
```javascript
window.crypto.subtle.wrapKey(
"raw", //the export format, must be "raw" (only available sometimes)
key, //the key you want to wrap, must export in 8 byte increments
wrappingKey, //the AES-KW key with "wrapKey" usage flag
{ //these are the wrapping key's algorithm options
name: "AES-KW",
}
)
.then(function(wrapped){
//returns an ArrayBuffer containing the encrypted data
console.log(new Uint8Array(wrapped));
})
.catch(function(err){
console.error(err);
});
```
#### AES-KW - unwrapKey
```javascript
window.crypto.subtle.unwrapKey(
"raw", //the import format, must be "raw" (only available sometimes)
wrapped, //the key you want to unwrap
wrappingKey, //the AES-KW key with "unwrapKey" usage flag
{ //these are the wrapping key's algorithm options
name: "AES-KW",
},
{ //this what you want the wrapped key to become (same as when wrapping)
name: "AES-GCM",
length: 256
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //the usages you want the unwrapped key to have
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
## HMAC
#### HMAC - generateKey
```javascript
window.crypto.subtle.generateKey(
{
name: "HMAC",
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
//length: 256, //optional, if you want your key length to differ from the hash function's block length
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["sign", "verify"] //can be any combination of "sign" and "verify"
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### HMAC - importKey
```javascript
window.crypto.subtle.importKey(
"jwk", //can be "jwk" or "raw"
{ //this is an example jwk key, "raw" would be an ArrayBuffer
kty: "oct",
k: "Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE",
alg: "HS256",
ext: true,
},
{ //this is the algorithm options
name: "HMAC",
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
//length: 256, //optional, if you want your key length to differ from the hash function's block length
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["sign", "verify"] //can be any combination of "sign" and "verify"
)
.then(function(key){
//returns the symmetric key
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### HMAC - exportKey
```javascript
window.crypto.subtle.exportKey(
"jwk", //can be "jwk" or "raw"
key //extractable must be true
)
.then(function(keydata){
//returns the exported key data
console.log(keydata);
})
.catch(function(err){
console.error(err);
});
```
#### HMAC - sign
```javascript
window.crypto.subtle.sign(
{
name: "HMAC",
},
key, //from generateKey or importKey above
data //ArrayBuffer of data you want to sign
)
.then(function(signature){
//returns an ArrayBuffer containing the signature
console.log(new Uint8Array(signature));
})
.catch(function(err){
console.error(err);
});
```
#### HMAC - verify
```javascript
window.crypto.subtle.verify(
{
name: "HMAC",
},
key, //from generateKey or importKey above
signature, //ArrayBuffer of the signature
data //ArrayBuffer of the data
)
.then(function(isvalid){
//returns a boolean on whether the signature is true or not
console.log(isvalid);
})
.catch(function(err){
console.error(err);
});
```
## DH
#### DH - generateKey
```javascript
window.crypto.subtle.generateKey(
{
name: "DH",
//NOTE: THIS IS A SMALL PRIME FOR TESTING ONLY! DO NOT USE IT FOR REAL!
//See http://datatracker.ietf.org/doc/rfc3526/ for better primes
prime: new Uint8Array([
255,255,255,255,255,255,255,255,201,15,218,162,33,104,194,52,196,198,98,139,
128,220,28,209,41,2,78,8,138,103,204,116,2,11,190,166,59,19,155,34,81,74,8,
121,142,52,4,221,239,149,25,179,205,58,67,27,48,43,10,109,242,95,20,55,79,225,
53,109,109,81,194,69,228,133,181,118,98,94,126,198,244,76,66,233,166,55,237,
107,11,255,92,182,244,6,183,237,238,56,107,251,90,137,159,165,174,159,36,17,
124,75,31,230,73,40,102,81,236,228,91,61,194,0,124,184,161,99,191,5,152,218,
72,54,28,85,211,154,105,22,63,168,253,36,207,95,131,101,93,35,220,163,173,
150,28,98,243,86,32,133,82,187,158,213,41,7,112,150,150,109,103,12,53,78,74,
188,152,4,241,116,108,8,202,35,115,39,255,255,255,255,255,255,255,255
]),
generator: new Uint8Array([2]),
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["deriveKey", "deriveBits"] //can be any combination of "deriveKey" and "deriveBits"
)
.then(function(key){
//returns a keypair object
console.log(key);
console.log(key.publicKey);
console.log(key.privateKey);
})
.catch(function(err){
console.error(err);
});
```
#### DH - importKey
```javascript
window.crypto.subtle.importKey(
"raw", //can be "raw" (public only), "spki" (public only), or "pkcs8" (private only)
new Uint8Array([ //this is an example raw key, "raw" would be an ArrayBuffer
203,25,0,203,43,75,46,159,217,37,185,181,25,220,71,187,112,195,251,233,152,56,206,
93,18,96,87,132,17,113,166,110,123,190,194,168,100,147,21,174,131,80,8,247,125,35,
210,70,103,141,152,173,99,74,34,132,92,134,216,55,171,186,89,167,189,217,164,119,
22,139,55,26,239,242,30,241,140,139,202,116,174,137,77,11,29,4,30,47,118,170,84,243,
97,132,86,58,24,82,36,149,45,185,23,172,67,162,48,43,110,251,175,20,102,237,113,148,
5,242,29,209,34,173,52,72,251,254,84,86,226,151,202,110,61,145,198,244,80,227,65,
203,118,217,91,45,58,172,165,224,122,230,50,135,120,124,37,190,186,204,103,218,19,
91,246,115,6,199,45,121,156,149,6,208,85,26,94,171,165,228,58,200,49,82,210,170,243,
154,190,15,2,225,143,159
]),
{ //these are the algorithm options
name: "DH",
//NOTE: THIS IS A SMALL PRIME FOR TESTING ONLY! DO NOT USE IT FOR REAL!
//See http://datatracker.ietf.org/doc/rfc3526/ for better primes
prime: new Uint8Array([
255,255,255,255,255,255,255,255,201,15,218,162,33,104,194,52,196,198,98,139,
128,220,28,209,41,2,78,8,138,103,204,116,2,11,190,166,59,19,155,34,81,74,8,
121,142,52,4,221,239,149,25,179,205,58,67,27,48,43,10,109,242,95,20,55,79,225,
53,109,109,81,194,69,228,133,181,118,98,94,126,198,244,76,66,233,166,55,237,
107,11,255,92,182,244,6,183,237,238,56,107,251,90,137,159,165,174,159,36,17,
124,75,31,230,73,40,102,81,236,228,91,61,194,0,124,184,161,99,191,5,152,218,
72,54,28,85,211,154,105,22,63,168,253,36,207,95,131,101,93,35,220,163,173,
150,28,98,243,86,32,133,82,187,158,213,41,7,112,150,150,109,103,12,53,78,74,
188,152,4,241,116,108,8,202,35,115,39,255,255,255,255,255,255,255,255
]),
generator: new Uint8Array([2]),
},
false, //whether the key is extractable (i.e. can be used in exportKey)
[] //use ["deriveKey", "deriveBits"] if importing a private key
)
.then(function(publicKey){
//returns a publicKey (or privateKey if you are importing a private key)
console.log(publicKey);
})
.catch(function(err){
console.error(err);
});
```
#### DH - exportKey
```javascript
window.crypto.subtle.exportKey(
"jwk", //can be "raw" (public or private), "spki" (public only), or "pkcs8" (private only)
publicKey //can be a publicKey or privateKey, as long as extractable was true
)
.then(function(keydata){
//returns the exported key data
console.log(keydata);
})
.catch(function(err){
console.error(err);
});
```
#### DH - deriveKey
```javascript
window.crypto.subtle.deriveKey(
{
name: "DH",
//NOTE: THIS IS A SMALL PRIME FOR TESTING ONLY! DO NOT USE IT FOR REAL!
//See http://datatracker.ietf.org/doc/rfc3526/ for better primes
prime: new Uint8Array([
255,255,255,255,255,255,255,255,201,15,218,162,33,104,194,52,196,198,98,139,
128,220,28,209,41,2,78,8,138,103,204,116,2,11,190,166,59,19,155,34,81,74,8,
121,142,52,4,221,239,149,25,179,205,58,67,27,48,43,10,109,242,95,20,55,79,225,
53,109,109,81,194,69,228,133,181,118,98,94,126,198,244,76,66,233,166,55,237,
107,11,255,92,182,244,6,183,237,238,56,107,251,90,137,159,165,174,159,36,17,
124,75,31,230,73,40,102,81,236,228,91,61,194,0,124,184,161,99,191,5,152,218,
72,54,28,85,211,154,105,22,63,168,253,36,207,95,131,101,93,35,220,163,173,
150,28,98,243,86,32,133,82,187,158,213,41,7,112,150,150,109,103,12,53,78,74,
188,152,4,241,116,108,8,202,35,115,39,255,255,255,255,255,255,255,255
]),
generator: new Uint8Array([2]),
public: publicKey, //a DH public key from generateKey or importKey
},
privateKey, //your DH private key from generateKey or importKey
{ //the key type you want to create based on the derived bits
name: "AES-CTR", //can be any AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH", or "HMAC")
//the generateKey parameters for that type of algorithm
length: 256, //can be 128, 192, or 256
},
false, //whether the derived key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //limited to the options in that algorithm's importKey
)
.then(function(key){
//returns the derived key
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### DH - deriveBits
```javascript
window.crypto.subtle.deriveBits(
{
name: "DH",
//NOTE: THIS IS A SMALL PRIME FOR TESTING ONLY! DO NOT USE IT FOR REAL!
//See http://datatracker.ietf.org/doc/rfc3526/ for better primes
prime: new Uint8Array([
255,255,255,255,255,255,255,255,201,15,218,162,33,104,194,52,196,198,98,139,
128,220,28,209,41,2,78,8,138,103,204,116,2,11,190,166,59,19,155,34,81,74,8,
121,142,52,4,221,239,149,25,179,205,58,67,27,48,43,10,109,242,95,20,55,79,225,
53,109,109,81,194,69,228,133,181,118,98,94,126,198,244,76,66,233,166,55,237,
107,11,255,92,182,244,6,183,237,238,56,107,251,90,137,159,165,174,159,36,17,
124,75,31,230,73,40,102,81,236,228,91,61,194,0,124,184,161,99,191,5,152,218,
72,54,28,85,211,154,105,22,63,168,253,36,207,95,131,101,93,35,220,163,173,
150,28,98,243,86,32,133,82,187,158,213,41,7,112,150,150,109,103,12,53,78,74,
188,152,4,241,116,108,8,202,35,115,39,255,255,255,255,255,255,255,255
]),
generator: new Uint8Array([2]),
public: publicKey, //a DH public key from generateKey or importKey
},
privateKey, //your DH private key from generateKey or importKey
256 //the number of bits you want to derive
)
.then(function(bits){
//returns the derived bits as an ArrayBuffer
console.log(new Uint8Array(bits));
})
.catch(function(err){
console.error(err);
});
```
## SHA
#### SHA-1 - digest
```javascript
window.crypto.subtle.digest(
{
name: "SHA-1",
},
new Uint8Array([1,2,3,4]) //The data you want to hash as an ArrayBuffer
)
.then(function(hash){
//returns the hash as an ArrayBuffer
console.log(new Uint8Array(hash));
})
.catch(function(err){
console.error(err);
});
```
#### SHA-256 - digest
```javascript
window.crypto.subtle.digest(
{
name: "SHA-256",
},
new Uint8Array([1,2,3,4]) //The data you want to hash as an ArrayBuffer
)
.then(function(hash){
//returns the hash as an ArrayBuffer
console.log(new Uint8Array(hash));
})
.catch(function(err){
console.error(err);
});
```
#### SHA-384 - digest
```javascript
window.crypto.subtle.digest(
{
name: "SHA-384",
},
new Uint8Array([1,2,3,4]) //The data you want to hash as an ArrayBuffer
)
.then(function(hash){
//returns the hash as an ArrayBuffer
console.log(new Uint8Array(hash));
})
.catch(function(err){
console.error(err);
});
```
#### SHA-512 - digest
```javascript
window.crypto.subtle.digest(
{
name: "SHA-512",
},
new Uint8Array([1,2,3,4]) //The data you want to hash as an ArrayBuffer
)
.then(function(hash){
//returns the hash as an ArrayBuffer
console.log(new Uint8Array(hash));
})
.catch(function(err){
console.error(err);
});
```
## CONCAT
#### CONCAT - importKey
```javascript
window.crypto.subtle.importKey(
"raw", //only "raw" is allowed
keydata, //your raw key data as an ArrayBuffer
{
name: "CONCAT",
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["deriveKey", "deriveBits"] //can be any combination of "deriveKey" and "deriveBits"
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### CONCAT - deriveKey
```javascript
window.crypto.subtle.deriveKey(
{
"name": "CONCAT",
algorithmId: ArrayBuffer, //?????? I don't know what this should be
partyUInfo: ArrayBuffer, //?????? I don't know what this should be
partyVInfo: ArrayBuffer, //?????? I don't know what this should be
publicInfo: ArrayBuffer, //?????? I don't know what this should be
privateInfo: ArrayBuffer, //?????? I don't know what this should be
hash: {name: "SHA-1"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
key, //your key from importKey
{ //the key type you want to create based on the derived bits
name: "AES-CTR", //can be any AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH", or "HMAC")
//the generateKey parameters for that type of algorithm
length: 256, //can be 128, 192, or 256
},
false, //whether the derived key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //limited to the options in that algorithm's importKey
)
.then(function(key){
//returns the derived key
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### CONCAT - deriveBits
```javascript
window.crypto.subtle.deriveBits(
{
"name": "CONCAT",
algorithmId: ArrayBuffer, //?????? I don't know what this should be
partyUInfo: ArrayBuffer, //?????? I don't know what this should be
partyVInfo: ArrayBuffer, //?????? I don't know what this should be
publicInfo: ArrayBuffer, //?????? I don't know what this should be
privateInfo: ArrayBuffer, //?????? I don't know what this should be
hash: {name: "SHA-1"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
key, //your key importKey
256 //the number of bits you want to derive
)
.then(function(bits){
//returns the derived bits as an ArrayBuffer
console.log(new Uint8Array(bits));
})
.catch(function(err){
console.error(err);
});
```
## HKDF-CTR
#### HKDF-CTR - importKey
```javascript
window.crypto.subtle.importKey(
"raw", //only "raw" is allowed
keydata, //your raw key data as an ArrayBuffer
{
name: "HKDF-CTR",
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["deriveKey", "deriveBits"] //can be any combination of "deriveKey" and "deriveBits"
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### HKDF-CTR - deriveKey
```javascript
window.crypto.subtle.deriveKey(
{
"name": "HKDF-CTR",
label: ArrayBuffer, //?????? I don't know what this should be
context: ArrayBuffer, //?????? I don't know what this should be
hash: {name: "SHA-1"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
key, //your key from importKey
{ //the key type you want to create based on the derived bits
name: "AES-CTR", //can be any AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH", or "HMAC")
//the generateKey parameters for that type of algorithm
length: 256, //can be 128, 192, or 256
},
false, //whether the derived key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //limited to the options in that algorithm's importKey
)
.then(function(key){
//returns the derived key
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### HKDF-CTR - deriveBits
```javascript
window.crypto.subtle.deriveBits(
{
"name": "HKDF-CTR",
label: ArrayBuffer, //?????? I don't know what this should be
context: ArrayBuffer, //?????? I don't know what this should be
hash: {name: "SHA-1"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
key, //your key importKey
256 //the number of bits you want to derive
)
.then(function(bits){
//returns the derived bits as an ArrayBuffer
console.log(new Uint8Array(bits));
})
.catch(function(err){
console.error(err);
});
```
## PBKDF2
#### PBKDF2 - generateKey
```javascript
//NOTE: This prompts the user to enter a password.
window.crypto.subtle.generateKey(
{
name: "PBKDF2",
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["deriveKey", "deriveBits"] //can be any combination of "deriveKey" and "deriveBits"
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### PBKDF2 - importKey
```javascript
window.crypto.subtle.importKey(
"raw", //only "raw" is allowed
window.crypto.getRandomValues(new Uint8Array(16)), //your password
{
name: "PBKDF2",
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["deriveKey", "deriveBits"] //can be any combination of "deriveKey" and "deriveBits"
)
.then(function(key){
//returns a key object
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### PBKDF2 - deriveKey
```javascript
window.crypto.subtle.deriveKey(
{
"name": "PBKDF2",
salt: window.crypto.getRandomValues(new Uint8Array(16)),
iterations: 1000,
hash: {name: "SHA-1"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
key, //your key from generateKey or importKey
{ //the key type you want to create based on the derived bits
name: "AES-CTR", //can be any AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH", or "HMAC")
//the generateKey parameters for that type of algorithm
length: 256, //can be 128, 192, or 256
},
false, //whether the derived key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //limited to the options in that algorithm's importKey
)
.then(function(key){
//returns the derived key
console.log(key);
})
.catch(function(err){
console.error(err);
});
```
#### PBKDF2 - deriveBits
```javascript
window.crypto.subtle.deriveBits(
{
"name": "PBKDF2",
salt: window.crypto.getRandomValues(new Uint8Array(16)),
iterations: 1000,
hash: {name: "SHA-1"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
key, //your key from generateKey or importKey
256 //the number of bits you want to derive
)
.then(function(bits){
//returns the derived bits as an ArrayBuffer
console.log(new Uint8Array(bits));
})
.catch(function(err){
console.error(err);
});
```
```typescript
const privateKeyBytes = jwkToBytes(privateKeyJwk)
const signatureBytes = crypto.sign(..., key: privateKeyBytes)
const signatureJWS = signatureToJwsSignature(signatureBytes, header, data)
const signatureJws = crypto.sign(..., key: privateKeyJwk, inputEncoder: jwkToBytes(), outputEncoder: ..)
```