# HTTP Client Crypto API reference

The `crypto` object provides access to the HTTP Client Crypto API, which supports cryptographic hash functions, HMAC, RSA, and ECDSA for generating HTTP signatures. This functionality is available through both convenience methods (`crypto.hmac`, hash algorithms) and an implementation of the `crypto.subtle` interface.

> **Note:**
> In the HTTP Client, all `crypto.subtle` operations are synchronous and return results directly.

The HTTP Client also supports JWT operations for generating, inspecting, and validating JSON Web Tokens directly in pre-request scripts using the `jwt.*` functions.

## Hash methods

| Method | Parameters | Description |
| --- | --- | --- |
|  `updateWithText`  |     `textInput` (string)       `encoding` (string): the encoding of `textInput`. Default is `UTF8`.     |  Updates a string to be transformed to a hash.  |
|  `updateWithHex`  |     `hexInput` (string)     |  Updates a hexadecimal string to be transformed to a hash.  |
|  `updateWithBase64`  |     `base64Input` (string)       `urlSafe` (boolean): enter `true` if the string is encoded using the URL-safe variant of Base64.     |  Updates a Base64 string to be transformed to a hash.  |
|  `digest().toHex()`  |  —  | Generates a hash and convert it to the hexadecimal format.  |
|  `digest().toBase64()`  |  `urlSafe` (boolean): enter `true` if you want to use the URL-safe variant of Base64  | Generates a hash and convert it to the Base64 format.  |

## HMAC methods

The `crypto.hmac` object enables you to use HMAC to sign HTTP requests. It has access to all [hash methods](#hash_methods) to generate hashes but also has methods to get the secret part of the token.

| Method | Parameters | Description |
| --- | --- | --- |
|  `withTextSecret`  |     `textSecret` (string)       `encoding` (string): the encoding of `textSecret`. Default is `UTF8`.     |  Puts the secret key to be used in HMAC.  |
|  `withHexSecret`  |     `hexSecret` (string)     |  Puts the secret key in the hexadecimal format.  |
|  `withBase64Secret`  |     `base64Input` (string)       `urlSafe` (boolean): enter `true` if the string is encoded using the URL-safe variant of Base64.     |  Puts the secret key in the Base64 format.  |

The HTTP Client supports HMAC with the SHA-2 and SHA-3 algorithm families. To use SHA-2 algorithms, you can call dedicated methods such as `crypto.hmac.sha256()` or `crypto.hmac.sha512()`. For SHA-3 algorithms, the format differs, and you use a single method with a parameter specifying the bit length, for example `crypto.hmac.sha3('512')` or `crypto.hmac.sha3('256')`.

Examples:

HMAC with SHA-2:

```JAVASCRIPT
< {%
    const signature = crypto.hmac.sha256()
        .withTextSecret(request.environment.get("secret")) // get variable from http-client.private.env.json
        .updateWithText(request.body.tryGetSubstituted())
        .digest().toHex();
    request.variables.set("signature", signature)

    const hash = crypto.sha256()
        .updateWithText(request.body.tryGetSubstituted())
        .digest().toHex();
    request.variables.set("hash", hash)
%}
POST https://httpbin.org/post
    X-My-Signature: {{signature}}
    X-My-Hash: {{hash}}
    Content-Type: application/json

{
    "prop": "value"
}
```

HMAC with SHA-3:

```JAVASCRIPT
< {%
    const signature = crypto.hmac.sha3('512')
            .withTextSecret('Secret')
            .updateWithText('Servus!')
            .digest().toHex();
    console.log(`signature: ${signature}`)
%}
POST https://examples.http-client.intellij.net/anything
```

## RSA methods

The `crypto.subtle` interface enables you to use RSA cryptography in pre-request scripts. The HTTP Client supports the [Web Crypto
API](https://w3c.github.io/webcrypto/#algorithms), which provides standard cryptographic functions such as key generation, encryption, decryption, digital signing, signature verification, and more.

| Method | Parameters | Description | Algorithm |
| --- | --- | --- | --- |
| `encrypt` |    `algorithm` (object): specify the encryption algorithm and its parameters. The exact object structure depends on the algorithm in use.     `key` (object): specify the `CryptoKey` containing the key for encryption.     `data` (`TypedArray`)    | Encrypts the provided data using the specified algorithm and key. | RSA-OAEP |
| `decrypt` |    `algorithm` (object): specify the decryption algorithm and its parameters. The exact object structure depends on the algorithm in use.     `key` (object): specify the `CryptoKey` containing the key for decryption.     `data` (`TypedArray`)    | Decrypts the encrypted data using the specified algorithm and key. | RSA-OAEP |
| `sign` | `algorithm` (object): specify the algorithm for generating a digital signature. The exact object structure depends on the algorithm in use.     `key` (object): specify the `CryptoKey` containing the key for signing. If `algorithm` identifies a public-key cryptosystem, the key is private.      `data` (`TypedArray`)   | Generates a digital signature using the specified algorithm and key. | RSASSA-PKCS1-v1_5, RSA-PSS |
| `verify` | `algorithm` (object): specify the algorithm for signature verification. The exact object structure depends on the algorithm in use.     `key` (object): specify the `CryptoKey` containing the key to verify the signature. Use a secret key for symmetric algorithms, or a public key for public-key algorithms.      `signature` (`TypedArray`)     `data` (`TypedArray`)   | Verifies a digital signature using the specified algorithm and key. | RSASSA-PKCS1-v1_5, RSA-PSS |
| `generateKey` |    `algorithm` (object): specify the algorithm that will define the type of key to generate.     `extractable` (boolean): enter `true` to allow for exporting the key with `crypto.subtle.exportKey()` or `crypto.subtle.wrapKey()`.     `keyUsages` (array of strings): specify the list of possible operations with the key.    | Generates a new key (for symmetric algorithms) or key pair (for public-key algorithms). | RSASSA-PKCS1-v1_5, RSA-PSS, RSA-OAEP |
| `importKey` |    `format` (string): specify the data format of the key to import. Possible values: `pkcs8`, `spki`.     `keyData` (`TypedArray`)     `algorithm` (object): specify the algorithm defining the type of key to import and provide algorithm-specific parameters.     `extractable` (boolean): enter `true` to allow for exporting the key with `crypto.subtle.exportKey()` or `crypto.subtle.wrapKey()`.     `keyUsages` (array of strings): specify the list of possible operations with the key.    | Imports a key in an external portable format and returns a `CryptoKey` object.  | RSASSA-PKCS1-v1_5, RSA-PSS, RSA-OAEP |
| `exportKey` |    `format` (string): specify a data format to export the key. Possible values: `pkcs8`, `spki`.     `key` (object): specify the `CryptoKey` to export.    | Exports a `CryptoKey` and returns a key in an external portable format. | RSASSA-PKCS1-v1_5, RSA-PSS, RSA-OAEP |

Example:

```JAVASCRIPT
< {%
    const keyPair = crypto.subtle.generateKey({
                name: "RSA-PSS",
                modulusLength: 2048,
                publicExponent: new Uint8Array([1, 0, 1]),
                hash: "SHA-256"
            },
            true,
            ["sign", "verify"])
    const text = "Hello, HTTP Client Pre Script!!!";
    const data = string2byteArray(text);
    const signature = crypto.subtle.sign(
            {
                name: "RSA-PSS",
            },
            keyPair.privateKey,
            data
    );
    const verified = crypto.subtle.verify(
            {
                name: "RSA-PSS",
            },
            keyPair.publicKey,
            signature,
            data);

    client.log(`${text}, verified: ${verified}`);
%}

GET https://example.com/api/path
```

## ECDSA methods

The HTTP Client supports ECDSA through the [Web Crypto
API](https://w3c.github.io/webcrypto/#algorithms), which provides the `SubtleCrypto` interface (`crypto.subtle`). You can generate or import keys and then sign and verify data in pre-request scripts.

| Method | Parameters | Description |
| --- | --- | --- |
| `sign` |    `algorithm`: specify the signing algorithm, for example `{ name: "ECDSA", hash: "SHA-256" }`.     `key` (object): provide the private `CryptoKey` with `"sign"` usage.      `data`: provide the data to be signed as `ArrayBuffer` or `TypedArray`.    | Creates a digital signature over the given data using a private ECDSA key. |
| `verify` | `algorithm` (object): specify the algorithm for signature verification. The exact object structure depends on the algorithm in use.     `key` (object): provide the public `CryptoKey`  with `"verify"` usage.      `signature` (`ArrayBuffer`)     `data` (`ArrayBuffer`)   | Verifies that the given signature is valid for the provided data and public ECDSA key. |
| `generateKey` |    `algorithm` (object): specify the algorithm and curve, for example, `{ name: "ECDSA", namedCurve: "P-256" }`.     `extractable` (boolean): enter `true` to allow for exporting the key with `crypto.subtle.exportKey()`.     `keyUsages` (array of strings): specify the list of possible operations with the key, for example, `["sign", "verify"]`.    | Generates a new elliptic curve key pair for the specified curve. Returns an object with `{ publicKey, privateKey }`.  |
| `importKey` |    `format` (string): specify the data format of the key to import. Possible values: `pkcs8`, `spki`.     `keyData` (`ArrayBuffer`, `TypedArray`, `DataView`, or `JSONWebKey`)     `algorithm` (object): specify the algorithm and curve, for example, `{ name: "ECDSA", namedCurve: "P-256" }`.     `extractable` (boolean): enter `true` to allow for exporting the key with `crypto.subtle.exportKey()`.     `keyUsages` (array of strings): specify the list of possible operations with the keys.    | Imports an existing elliptic curve key and returns a `CryptoKey`. The supported format depends on whether the key is public or private. |
| `exportKey` |    `format` (string): specify a data format to export the key. Possible values: `pkcs8`, `spki`.     `key` (object): specify the `CryptoKey` to export.    | Exports the given ECDSA key in the specified format. Returns binary data (`ArrayBuffer`) for PKCS8/SPKI/RAW, or a JSON object for JWK. |

Example:

```JAVASCRIPT
< {%
const base64publicKey = 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEn8E8vCgnmyDISke4RQVt0uwhE0AFL61crfJ7gmKkLgISv+eV5zAB1GBVQ/mj/4bZO8yJnFCrNGILHN59aCEEfA=='
const base64privateKey = 'MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgXMpTO9h9dsmz9f9XfpvdUbU8PGt7ZMiN95Irv0XAgQyhRANCAASfwTy8KCebIMhKR7hFBW3S7CETQAUvrVyt8nuCYqQuAhK/55XnMAHUYFVD+aP/htk7zImcUKs0Ygsc3n1oIQR8'
const privateKey = crypto.subtle.importKey(
        'pkcs8',
        Uint8Array.from(atob(base64privateKey), c => c.codePointAt(0)),
        { name: "ECDSA", namedCurve: "P-256" },
        true,
        ["sign"]
)

const msg = "Hello from HTTP Client!"
const signature = crypto.subtle.sign(
        { name: "ECDSA", hash: "SHA-256" },
        privateKey,
        Uint8Array.from(msg, c => c.charCodeAt(0))
)

const publicKey = crypto.subtle.importKey(
        'spki',
        Uint8Array.from(atob(base64publicKey), c => c.codePointAt(0)),
        { name: "ECDSA", namedCurve: "P-256" },
        true,
        ["verify"]
)
const verificationResult = crypto.subtle.verify(
        { name: "ECDSA", hash: "SHA-256" },
        publicKey,
        signature,
        Uint8Array.from(msg, c => c.charCodeAt(0))
)
console.log(`verificationResult: ${verificationResult}`)
%}
GET https://example.com/api/path

```

## JWT signing

HTTP Client pre-request scripts support creating and signing [JSON Web Tokens (JWTs)](https://datatracker.ietf.org/doc/html/rfc7519). A JWT consists of three parts: a base64url-encoded header, a base64url-encoded payload (claims), and a cryptographic signature.

The `jwt.*` functions make it possible to generate, inspect, and validate tokens directly in your requests. Signed JWTs can be stored in pre-request variables (for example, `jwt_token`) and then used to authenticate requests.

For JWT signing, HTTP Client supports the same algorithms as commonly used libraries like [node/jsonwebtoken](https://github.com/auth0/node-jsonwebtoken/blob/master/README.md), including:

* HS256 / HS384 / HS512 — HMAC with SHA-256/SHA-384/SHA-512

* RS256/RS384/RS512 — RSASSA-PKCS1-v1_5 with SHA-256/SHA-384/SHA-512

* PS256/PS384/PS512 — RSA-PSS with SHA-256/SHA-384/SHA-512

* ES256/ES384/ES512 — ECDSA with SHA-256/SHA-384/SHA-512

| Method | Parameters | Description |
| --- | --- | --- |
| `jwt.sign` |    `payload`: specify an object literal, buffer or string representing a valid JSON.     `key`: specify a secret string or bytes for HMAC, or a private key (`CryptoKey` / PEM) for RSA or ECDSA.     `options`: specify an object with the `algorithm` (HS256, RS256, PS256, ES256, ES384, and so on) and standard claims (for example, `issuer`, `audience`).    | Create and sign a JWT. |
| `jwt.verify` |    `token`: specify a JWT string to verify.     `key`: sprcify a secret (HMAC) or public key (`CryptoKey` / PEM) for RSA/ECDSA.     `options`: specify an object with the `algorithm` (HS256, RS256, PS256, ES256, ES384, and so on) and standard claims (for example, `issuer`, `audience`).    | Verify a JWT’s signature and optionally enforce claims. |
| `jwt.decode` |    `token`: specify a JWT string to decode.    | Decode a JWT without verifying its signature (for inspection or debugging). |

The following example of RSA-PSS signing demonstrates:

* Generating an RSA key pair

* Signing and verifying an arbitrary message with RSA-PSS

* Creating and verifying a JWT using PS256

* Exporting the public key to PEM (`spki`) so that external tools can verify it

```JAVASCRIPT
            
< {%
    let algorithm = {
        name: 'RSA-PSS',
        modulusLength: 2048,                       // 2048 or 4096 bits recommended
        publicExponent: new Uint8Array([1, 0, 1]), // 65537 (standard exponent)
        hash: "SHA-256"
    };
    const pair = crypto.subtle.generateKey(algorithm,
            true,
            ['sign', 'verify']);

    let otherClaim = 'Servus, HTTP Client Pre Script!!!';

    const rsaSignature = crypto.subtle.sign({
                name: "RSA-PSS",
                saltLength: 32
            },
            pair.privateKey,
            Uint8Array.from(otherClaim, c => c.charCodeAt(0)))

    console.log(`verify ${otherClaim}: ${crypto.subtle.verify({name: "RSA-PSS", saltLength: 32}, pair.publicKey, rsaSignature, Uint8Array.from(otherClaim, c => c.charCodeAt(0)))}`);


    const rsaJwt = jwt.sign({
        other_claim: otherClaim,
    }, pair.privateKey, {
        algorithm: 'PS256'
    })


    console.log(`RSA JWT: ${rsaJwt}`)

    console.log(`RSA verification: ${jwt.verify(rsaJwt, pair.publicKey, {algorithm: 'PS256'})}`)

    let publicKey = btoa(String.fromCharCode(...new Uint8Array(crypto.subtle.exportKey("spki", pair.publicKey))));
    console.log(`public key: \n-----BEGIN PUBLIC KEY-----\n${publicKey.match(/.{1,64}/g).join('\n')}\n-----END PUBLIC KEY-----`)


%}
GET examples.http-client.intellij.net/path
    
```

The next example demonstrates how to generate, decode, and verify a JWT using the HS256 algorithm (HMAC with SHA-256). The token includes the `aud` (audience) claim, which is validated during verification.

```JAVASCRIPT
            
< {%
    const signature = jwt.sign({
        other_claim: "some value",
        aud:['jetbrains']
    }, client.variables.file.get('secret'))

    console.log(`signature: ${jwt.decode(signature).payload.aud}`)


    client.variables.global.set("jwt_token", signature)
    console.log(jwt.verify(signature, client.variables.file.get('secret'), {
        audience: 'jetbrains',
        algorithm: 'HS256'
    }))
    console.log(signature)
%}

GET examples.http-client.intellij.net/path
            
```

