Skip to content

Commit d75c03a

Browse files
webcrypto: crypto avaliable globally
Apply suggestions from code review Co-authored-by: Heitor Tashiro Sergent <[email protected]>
1 parent 59e8334 commit d75c03a

36 files changed

+1851
-0
lines changed

docs/sources/.eslintrc.js

+1
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,6 @@ module.exports = {
4646
clearInterval: 'readonly',
4747
setTimeout: 'readonly',
4848
clearTimeout: 'readonly',
49+
crypto: 'readonly',
4950
},
5051
};

docs/sources/k6/next/javascript-api/_index.md

+4
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ The [`k6/browser` module](https://grafana.com/docs/k6/<K6_VERSION>/javascript-ap
7373

7474
{{< docs/shared source="k6" lookup="javascript-api/k6-ws.md" version="<K6_VERSION>" >}}
7575

76+
## crypto
77+
78+
{{< docs/shared source="k6" lookup="javascript-api/crypto.md" version="<K6_VERSION>" >}}
79+
7680
## Error codes
7781

7882
The following specific error codes are currently defined:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
---
2+
title: 'crypto'
3+
description: 'k6 WebCrypto API implementation'
4+
weight: 14
5+
---
6+
7+
# crypto
8+
9+
With this module, you can use the [WebCrypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) in your k6 scripts. However, note that this API is not yet fully implemented and some algorithms and features might still be missing.
10+
11+
The Web Crypto API is a JavaScript API for performing cryptographic operations such as encryption, decryption, digital signature generation and verification, and key generation and management. It provides a standard interface to access cryptographic functionality, which can help ensure that cryptographic operations are performed correctly and securely.
12+
13+
## API
14+
15+
The module is a top-level `crypto` object with the following properties and methods:
16+
17+
| Interface/Function | Description |
18+
| :------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
19+
| [getRandomValues](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/getrandomvalues) | Fills the passed `TypedArray` with cryptographically sound random values. |
20+
| [randomUUID](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/randomuuid) | Returns a randomly generated, 36 character long v4 UUID. |
21+
| [subtle](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/subtlecrypto) | The [SubtleCrypto](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/subtlecrypto) interface provides access to common cryptographic primitives, such as hashing, signing, encryption, or decryption. |
22+
23+
## Example
24+
25+
{{< code >}}
26+
27+
```javascript
28+
export default async function () {
29+
const plaintext = stringToArrayBuffer('Hello, World!');
30+
31+
/**
32+
* Generate a symmetric key using the AES-CBC algorithm.
33+
*/
34+
const key = await crypto.subtle.generateKey(
35+
{
36+
name: 'AES-CBC',
37+
length: 256,
38+
},
39+
true,
40+
['encrypt', 'decrypt']
41+
);
42+
43+
/**
44+
* Encrypt the plaintext using the AES-CBC key with
45+
* have generated.
46+
*/
47+
const iv = crypto.getRandomValues(new Uint8Array(16));
48+
const ciphertext = await crypto.subtle.encrypt(
49+
{
50+
name: 'AES-CBC',
51+
iv: iv,
52+
},
53+
key,
54+
plaintext
55+
);
56+
57+
/**
58+
* Decrypt the ciphertext using the same key to verify
59+
* that the resulting plaintext is the same as the original.
60+
*/
61+
const deciphered = await crypto.subtle.decrypt(
62+
{
63+
name: 'AES-CBC',
64+
iv: iv,
65+
},
66+
key,
67+
ciphertext
68+
);
69+
70+
console.log(
71+
'deciphered text == original plaintext: ',
72+
arrayBufferToHex(deciphered) === arrayBufferToHex(plaintext)
73+
);
74+
}
75+
76+
function arrayBufferToHex(buffer) {
77+
return [...new Uint8Array(buffer)].map((x) => x.toString(16).padStart(2, '0')).join('');
78+
}
79+
80+
function stringToArrayBuffer(str) {
81+
const buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char
82+
const bufView = new Uint16Array(buf);
83+
for (let i = 0, strLen = str.length; i < strLen; i++) {
84+
bufView[i] = str.charCodeAt(i);
85+
}
86+
return buf;
87+
}
88+
```
89+
90+
{{< /code >}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
title: 'AesCbcParams'
3+
description: 'AesCbcParams represents the object that should be passed as the algorithm parameter into the encrypt and decrypt operation when using the AES-CBC algorithm.'
4+
weight: 04
5+
---
6+
7+
# AesCbcParams
8+
9+
The `AesCbcParams` object represents the object that should be passed as the algorithm parameter into the [encrypt](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/subtlecrypto/encrypt) and [decrypt](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/subtlecrypto/decrypt) operation when using the AES-CBC algorithm.
10+
11+
For more details, head to the [MDN Web Crypto API documentation on AES-CBC](https://developer.mozilla.org/en-US/docs/Web/API/AesCbcParams).
12+
13+
## Properties
14+
15+
| Property | Type | Description |
16+
| :------- | :----------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17+
| name | `string` | Should be set to `AES-CBC`. |
18+
| iv | `ArrayBuffer`, `TypedArray`, or `DataView` | The initialization vector. Must be 16 bytes, unpredictable and cryptographically random. Yet, it doesn't need to be secret and can be transmitted along with the ciphertext. |
19+
20+
## Example
21+
22+
{{< code >}}
23+
24+
```javascript
25+
export default async function () {
26+
const plaintext = stringToArrayBuffer('Hello, World!');
27+
28+
/**
29+
* Generate a symmetric key using the AES-CBC algorithm.
30+
*/
31+
const key = await crypto.subtle.generateKey(
32+
{
33+
name: 'AES-CBC',
34+
length: 256,
35+
},
36+
true,
37+
['encrypt', 'decrypt']
38+
);
39+
40+
/**
41+
* Encrypt the plaintext using the AES-CBC key with
42+
* have generated.
43+
*/
44+
const ciphertext = await crypto.subtle.encrypt(
45+
{
46+
name: 'AES-CBC',
47+
iv: crypto.getRandomValues(new Uint8Array(16)),
48+
},
49+
key,
50+
plaintext
51+
);
52+
}
53+
54+
function stringToArrayBuffer(str) {
55+
const buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char
56+
const bufView = new Uint16Array(buf);
57+
for (let i = 0, strLen = str.length; i < strLen; i++) {
58+
bufView[i] = str.charCodeAt(i);
59+
}
60+
return buf;
61+
}
62+
```
63+
64+
{{< /code >}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
title: 'AesCtrParams'
3+
description: 'AesCtrParams represents the object that should be passed as the algorithm parameter into the encrypt and decrypt operation when using the AES-CTR algorithm.'
4+
weight: 05
5+
---
6+
7+
# AesCtrParams
8+
9+
The `AesCtrParams` object represents the object that should be passed as the algorithm parameter into the [encrypt](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/subtlecrypto/encrypt) and [decrypt](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/subtlecrypto/decrypt) operation when using the AES-CTR algorithm.
10+
11+
For more details, head to the MDN Web Crypto API documentation on [AES-CTR](https://developer.mozilla.org/en-US/docs/Web/API/AesCtrParams).
12+
13+
## Properties
14+
15+
| Property | Type | Description |
16+
| :------- | :----------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------- |
17+
| name | `string` | Should be set to `AES-CTR`. |
18+
| counter | `ArrayBuffer`, `TypedArray`, or `DataView` | The initial value of the counter block. This must be 16-bytes long, like the AES block size. |
19+
| length | `number` | The number of bits in the counter block that are used for the actual counter. It is recommended to use 64 (half of the counter block). |
20+
21+
## Example
22+
23+
{{< code >}}
24+
25+
```javascript
26+
export default async function () {
27+
const plaintext = stringToArrayBuffer('Hello, World!');
28+
29+
/**
30+
* Generate a symmetric key using the AES-CTR algorithm.
31+
*/
32+
const key = await crypto.subtle.generateKey(
33+
{
34+
name: 'AES-CTR',
35+
length: 256,
36+
},
37+
true,
38+
['encrypt', 'decrypt']
39+
);
40+
41+
/**
42+
* Encrypt the plaintext using the AES-CTR key with
43+
* have generated.
44+
*/
45+
const ciphertext = await crypto.subtle.encrypt(
46+
{
47+
name: 'AES-CTR',
48+
counter: crypto.getRandomValues(new Uint8Array(16)),
49+
length: 128,
50+
},
51+
key,
52+
plaintext
53+
);
54+
}
55+
56+
function stringToArrayBuffer(str) {
57+
const buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char
58+
const bufView = new Uint16Array(buf);
59+
for (let i = 0, strLen = str.length; i < strLen; i++) {
60+
bufView[i] = str.charCodeAt(i);
61+
}
62+
return buf;
63+
}
64+
```
65+
66+
{{< /code >}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
title: 'AesGcmParams'
3+
description: 'AesGcmParams represents the object that should be passed as the algorithm parameter into the encrypt and decrypt operation when using the AES-GCM algorithm.'
4+
weight: 06
5+
---
6+
7+
# AesGcmParams
8+
9+
The `AesGcmParams` object represents the object that should be passed as the algorithm parameter into the [encrypt](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/subtlecrypto/encrypt) and [decrypt](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/subtlecrypto/decrypt) operation when using the AES-GCM algorithm.
10+
11+
For more details, head to the [MDN Web Crypto API documentation on AES-GCM](https://developer.mozilla.org/en-US/docs/Web/API/AesGcmParams).
12+
13+
## Properties
14+
15+
| Property | Type | Description |
16+
| :------------------------ | :----------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17+
| name | `string` | Should be set to `AES-GCM`. |
18+
| iv | `ArrayBuffer`, `TypedArray`, or `DataView` | The initialization vector. It must be 12 bytes long, unpredictable and cryptographically random. It must be unique for every encryption operation carried out with a given key. Never reuse an iv with the same key. Yet, it doesn't need to be secret and can be transmitted along with the ciphertext. |
19+
| additionalData (optional) | `ArrayBuffer`, `TypedArray` or `DataView` | Additional data that should be authenticated, but not encrypted. It must be included in the calculation of the authentication tag, but not encrypted itself. |
20+
| tagLength (optional) | `number` | The length of the authentication tag in bits. Should be set, and will default to 96. |
21+
22+
## Example
23+
24+
{{< code >}}
25+
26+
```javascript
27+
export default async function () {
28+
const plaintext = stringToArrayBuffer('Hello, World!');
29+
30+
/**
31+
* Generate a symmetric key using the AES-CBC algorithm.
32+
*/
33+
const key = await crypto.subtle.generateKey(
34+
{
35+
name: 'AES-GCM',
36+
length: 256,
37+
},
38+
true,
39+
['encrypt', 'decrypt']
40+
);
41+
42+
/**
43+
* Encrypt the plaintext using the AES-CBC key with
44+
* have generated.
45+
*/
46+
const ciphertext = await crypto.subtle.encrypt(
47+
{
48+
name: 'AES-GCM',
49+
iv: crypto.getRandomValues(new Uint8Array(12)),
50+
},
51+
key,
52+
plaintext
53+
);
54+
}
55+
56+
function stringToArrayBuffer(str) {
57+
const buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char
58+
const bufView = new Uint16Array(buf);
59+
for (let i = 0, strLen = str.length; i < strLen; i++) {
60+
bufView[i] = str.charCodeAt(i);
61+
}
62+
return buf;
63+
}
64+
```
65+
66+
{{< /code >}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
title: 'AesKeyGenParams'
3+
description: 'AesKeyGenParams represents the object that should be passed as the algorithm parameter into the generateKey operation, when generating an AES key.'
4+
weight: 07
5+
---
6+
7+
# AesKeyGenParams
8+
9+
The `AesKeyGenParams` object represents the object that should be passed as the algorithm parameter into the [generateKey](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/subtlecrypto/generatekey) operation when generating an AES key.
10+
11+
## Properties
12+
13+
| Property | Type | Description |
14+
| :------- | :------- | :---------------------------------------------------------------------------------- |
15+
| name | `string` | The name of the algorithm. Possible values are `AES-CBC`, `AES-CTR`, and `AES-GCM`. |
16+
| length | `number` | The length of the key in bits. Possible values are 128, 192 or 256. |
17+
18+
## Example
19+
20+
{{< code >}}
21+
22+
```javascript
23+
export default async function () {
24+
const key = await crypto.subtle.generateKey(
25+
{
26+
name: 'AES-CBC',
27+
length: 256,
28+
},
29+
true,
30+
['encrypt', 'decrypt']
31+
);
32+
}
33+
```
34+
35+
{{< /code >}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
title: 'CryptoKey'
3+
description: 'CryptoKey represents a cryptographic key used for encryption, decryption, signing, or verification.'
4+
weight: 02
5+
---
6+
7+
# CryptoKey
8+
9+
The `CryptoKey` object represents a cryptographic key used for [encryption](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/subtlecrypto/encrypt),[decryption](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/subtlecrypto/decrypt),[signing](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/subtlecrypto/sign), or [verification](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/subtlecrypto/verify) within the webcrypto module. The `CryptoKey` object is created using the SubtleCrypto.generateKey() or SubtleCrypto.importKey() methods.
10+
11+
## Properties
12+
13+
| Property | Type | Description |
14+
| :---------- | :--------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
15+
| type | `string` | Indicates the type of the key material. Possible values are `public`, `private`, `secret`, `unspecified`, or `unknown`. |
16+
| extractable | `boolean` | Indicates whether the raw key material can be exported. |
17+
| algorithm | `object` | An object containing the algorithm used to generate or import the key. |
18+
| usages | `string[]` | An array of strings indicating the cryptographic operations that the key can be used for. Possible values are `encrypt`, `decrypt`, `sign`, `verify`, `deriveKey`, `deriveBits`, `wrapKey`, and `unwrapKey`. |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
title: 'CryptoKeyPair'
3+
description: 'CryptoKeyPair represents an asymmetric key pair with public and private keys.'
4+
weight: 08
5+
---
6+
7+
# CryptoKeyPair
8+
9+
The `CryptoKeyPair` object represents an asymmetric key pair with public and private keys.
10+
11+
The [`generateKey`](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/subtlecrypto/generatekey/) method can be used to create `CryptoKeyPair` object for asymmetric algorithms such as `ECDH` or `ECDSA`.
12+
13+
## Properties
14+
15+
| Property | Type | Description |
16+
| :--------- | :-------------------------------------------------------------------------------------- | :------------- |
17+
| publicKey | [`CryptoKey`](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/cryptokey) | A public key. |
18+
| privateKey | [`CryptoKey`](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/crypto/cryptokey) | A private key. |

0 commit comments

Comments
 (0)