# Encryption

**Encryption Overview**

We prioritize the security of your data. To ensure this, we employ encryption for the data transmitted through our Public API and Webhooks.

**Available Encryption Methods**

An encryption method and keys are provided on the ["Application"](/home/get-started/application.md) page of your account. These method and keys are essential for encrypting and decrypting data exchanged between your application and our services.

* **aes-256-cbc**
  * Keys Required:
    * **Crypto Key**: Used for encrypting and decrypting your JSON payload.
    * **HMAC Key**: Used to generate a signature that verifies the integrity and authenticity of your data
  * Header Requirement:
    * The HMAC signature must be included in the request headers **x-allpass-signature**
* **aes-256-gcm**
  * Keys Required:
    * **Crypto Key**: Used for encrypting and decrypting your JSON payload.
  * Header Requirement:
    * Although this method doesn’t require an additional HMAC key, the authentication tag (auth tag) generated during encryption must be provided in the headers **x-allpass-signature**

**Sending Data to Our Public API**

You have the option to send data to our Public API either encrypted or unencrypted, depending on your preference and security requirements.

* **Encrypted Data**: To send encrypted data, use the encryption keys provided on the ["Application"](/home/get-started/application.md) page. Encrypt your data before sending it to our API.The encrypted data should be included in the payload as follows:

```json
{
  "data": "encryptedString"
}
```

* **Unencrypted Data**: If you prefer, you can also send data without encryption. This option is available for clients who may not require the added security layer.

**Receiving Data from  Public  API and Webhooks**

All data sent to you via our Public API or Webhooks is encrypted using the same encryption keys found on the ["Application"](/home/get-started/application.md) page. Ensure you decrypt the incoming data using this key to access the information.

**Steps for Integration**

* **Retrieve Your Keys:**
  * Log in to your account and navigate to the ["Application"](/home/get-started/application.md) **page**.
  * For **aes-256-cbc**, retrieve both your Secret Key and your HMAC Key.
  * For **aes-256-gcm**, retrieve your Secret Key.
* **Encrypt Your Data:**
  * **For aes-256-cbc:**
    * Encrypt your JSON payload using the Secret Key.
    * Generate an HMAC signature using your HMAC Key.
  * **For aes-256-gcm:**
    * Encrypt your JSON payload using the Secret Key.
    * Extract the authentication tag (auth tag) during encryption.
* **Send Data to Public API**:
  * Payload Format:
    * Encrypted: Send your encrypted data to our Public API endpoint.&#x20;
  * &#x20;Headers:
    * For **aes-256-cbc:**\
      Attach the HMAC signature, e.g., **`x-allpass-signature: yourHMACvalue`**.
    * For **aes-256-gcm:**\
      Attach the authentication tag, e.g., **`x-allpass-signature: yourAuthTagValue`** .

```json
{
  "data": "encryptedString"
}
```

&#x20;         &#x20;

* **Receive and Decrypt Data:**
  * Use your Crypto Key to decrypt the incoming payload.
  * **For aes-256-cbc:**\
    Validate the HMAC signature from the headers using your HMAC Key.
  * **For aes-256-gcm:**\
    Use the auth tag provided in the headers to ensure correct decryption and data integrity.

**Example Code Snippets**

Here are some example code snippets to help you get started with encryption and decryption using your key:

**Encrypting Data**:

* **aes-256-cbc :**

```javascript
const crypto = require('crypto');
const cryptoKey = 'your-encryption-key';
const hmacKey = 'your-hmac-key';

const algorithm = 'aes-256-cbc';

function encrypt(text) {

    const keyBuff = Buffer.from(cryptoKey, 'hex');
    const iv = crypto.randomBytes(16);
    const cipher = crypto.createCipheriv(algorithm, keyBuff, iv);
    let encrypted = cipher.update(data, 'utf8', 'hex');
    encrypted += cipher.final('hex');

    const payload = iv.toString('hex') + encrypted;

    const hmacKeyBuff = Buffer.from(hmacKey, 'hex');
    const hmac = crypto.createHmac('sha256', hmacKeyBuff);
    hmac.update(payload);
    const hmacDigest = hmac.digest('hex');

    return {
      payload,
      signature: hmacDigest,
    };
}

const data = JSON.stringify({ key: 'value' });
const { payload, signature } = encrypt(data);
const request = { data: encryptedData };
console.log(request);
```

* **aes-256-gcm**

```javascript
const crypto = require('crypto');
const cryptoKey = 'your-encryption-key';
const algorithm = 'aes-256-gcm';

function encrypt(text) {
    const keyBuff = Buffer.from(cryptoKey, 'hex');
    const iv = crypto.randomBytes(12);
    const cipher = crypto.createCipheriv(algorithm, keyBuff, iv);

    const encrypted = Buffer.concat([
      cipher.update(data, 'utf8'),
      cipher.final(),
    ]);
    
    const authTag = cipher.getAuthTag();

    return {
      payload: iv.toString('hex') + encrypted.toString('hex'),
      signature: authTag.toString('hex'),
    };
}

const data = JSON.stringify({ key: 'value' });
const { payload, signature } = encrypt(data);
const request = { data: encryptedData };
console.log(request);
```

**Decrypting Data**:

* **aes-256-cbc:**

```javascript
const crypto = require('crypto');

function decryptData(
  encryptedTextWithIv: string, 
  cryptoKey: string,
  hmacKey: string,
  signature: string
): string {

      const hmacKeyBuff = Buffer.from(hmacKey, 'hex');
      const hmac = crypto.createHmac('sha256', hmacKeyBuff);
      hmac.update(encryptedTextWithIv);

      const computedSignature = hmac.digest('hex');

      if (computedSignature !== signature) {
        throw new Error('Invalid signature');
      }

    const keyBuff = Buffer.from(cryptoKey, 'hex');
    const iv = Buffer.from(encryptedTextWithIv.slice(0, 32), 'hex');
    const encryptedText = encryptedTextWithIv.slice(32);
    const decipher = crypto.createDecipheriv('aes-256-cbc', keyBuff, iv);
    let decrypted = decipher.update(encryptedText, 'hex', 'utf8');
    decrypted += decipher.final('utf8');

    return decrypted;
}

const cryptoKey = `*************`; // Your crypt key from application page
const hmacKey = `*************`; // Your hmac key from application page

const signature = response.headers['x-allpass-signature']

const encryptedDataString = '... Encrypted data in Base64 ...';
const decryptedDataString = decryptData( encryptedDataString, 
                                         cryptoKey, 
                                         hmacKey, 
                                         signature
                                       );

console.log('Decrypted data object:', JSON.parse(decryptedDataString));
```

* **aes-256-gcm:**

```typescript
const crypto = require('crypto');

function decryptData(
  encryptedTextWithIv: string, 
  cryptoKey: string,
  signature: string
): string {
    
    const iv = Buffer.from(encryptedTextWithIv.slice(0, 24), 'hex');
    const encryptedData = encryptedTextWithIv.slice(24);

    const decipher = crypto.createDecipheriv(
      'aes-256-gcm',
      Buffer.from(cryptoKey, 'hex'),
      iv,
    );
    decipher.setAuthTag(Buffer.from(signature, 'hex'));

    const decrypted = Buffer.concat([
      decipher.update(Buffer.from(encryptedData, 'hex')),
      decipher.final(),
    ]);

    return decrypted.toString('utf8');
}

const cryptoKey = `*************`; // Your crypt key from application page

const signature = response.headers['x-allpass-signature']

const encryptedDataString = '... Encrypted data in Base64 ...';
const decryptedDataString = decryptData( encryptedDataString, 
                                         cryptoKey,
                                         signature
                                       );

console.log('Decrypted data object:', JSON.parse(decryptedDataString));
```

#### Decrypting Stream Files

In addition to handling encrypted data through our Public API and Webhooks, you may also need to decrypt stream files received from our services. Below are the steps and code snippets to help you decrypt these stream files effectively.

* **Encryption Method:**\
  For stream file operations, our system exclusively uses **aes-256-cbc** encryption. Regardless of any other encryption method used elsewhere in your integration, stream files must be processed using **aes-256-cbc**.
* **Key Requirement:**\
  Only the **secret key** is required to decrypt stream file data. No HMAC signature is needed or verified for stream files.
* **Implication for Alternate Methods:**\
  If you opt to use another encryption method (for example, **aes-256-gcm**) when handling other data, please note that stream file data will still be decrypted using **aes-256-cbc** with only the secret key. Any HMAC signature provided with other data is ignored for stream files.

**Steps for Decrypting Stream Files**

1. **Retrieve Initialization Vector (IV):** The IV for the decryption process is provided in the response headers of the stream file. You can retrieve it using the following code:

   ```javascript
   const iv = Buffer.from(response.headers['x-initialization-vector'], 'hex');
   ```
2. **Decrypt Stream Data:**
   * Use the IV and the encryption key to decrypt the incoming stream file data.
   * The length of the IV is 16 bytes.

**Example Code Snippet**

Here's an example of how to decrypt a stream file:

```javascript
const crypto = require('crypto');
const fs = require('fs');
const http = require('http');
const { promisify } = require('util');
const { pipeline } = require('stream');

const pipelineAsync = promisify(pipeline);

async function downloadAndDecryptFile(url, outputPath, encryptionKey) {
  try {
    const response = await new Promise((resolve, reject) => {
      const request = http.get(url, {
        headers: {
          'X-Private-App-Key': 'string',
        },
      }, (response) => {
        if (response.statusCode !== 200) {
          reject(new Error(`Failed to get '${url}' (${response.statusCode})`));
        } else {
          resolve(response);
        }
      });

      request.on('error', (err) => {
        reject(err);
      });
    });

    // Retrieve the IV from the headers
    const iv = Buffer.from(response.headers['x-initialization-vector'], 'hex');
    if (!iv || iv.length !== 16) {
      throw new Error('Invalid or missing initialization vector (IV)');
    }

    const keyBuff = Buffer.from(encryptionKey, 'hex');
    // Create a decipher for decryption
    const decipher = crypto.createDecipheriv('aes-256-cbc', keyBuff, iv);

    // Create a write stream for the output file
    const writeStream = fs.createWriteStream(outputPath);

    // Pipe the encrypted stream through the decipher and into the write stream
    await pipelineAsync(response, decipher, writeStream);
    console.log('File downloaded and decrypted successfully.');
  } catch (err) {
    console.error('Error downloading or decrypting file:', err);
  }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.elkyc.com/home/integration/encryption.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
