> ## Documentation Index
> Fetch the complete documentation index at: https://developer.moneyone.in/llms.txt
> Use this file to discover all available pages before exploring further.

# AES-256-GCM

> Complete guide for AES-256-GCM encryption implementation in PFM APIs

## Overview

AES-256-GCM is our primary encryption mechanism for securing sensitive API communications.

### Key Features

* **256-bit encryption key** for strong security
* **96-bit initialization vector (IV)** for GCM mode
* **128-bit authentication tag** for integrity verification
* **Base64URL encoding** for safe transmission

### Key Exchange Process

1. 256-bit AES key and 96-bit IV are generated by us
2. Keys are securely shared with the client
3. Both the parties use the same key-IV pair for encryption/decryption

## Implementation Examples

### Encryption (Client-side)

<CodeGroup>
  ```java Java theme={null}
  import javax.crypto.Cipher;
  import javax.crypto.spec.GCMParameterSpec;
  import javax.crypto.spec.SecretKeySpec;
  import java.util.Base64;

  public class PFMEncryption {

      public static String encryptPayload(String jsonPayload, String key, String iv) {
          try {
              // Decode the Base64 encoded key and IV
              byte[] encryptionKey = Base64.getDecoder().decode(key);
              byte[] encryptionIv = Base64.getDecoder().decode(iv);

              // Convert JSON to bytes
              byte[] plaintextBytes = jsonPayload.getBytes("UTF-8");

              // Setup AES-GCM encryption
              SecretKeySpec keySpec = new SecretKeySpec(encryptionKey, "AES");
              GCMParameterSpec gcmSpec = new GCMParameterSpec(128, encryptionIv);

              Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
              cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmSpec);

              // Encrypt and encode
              byte[] encryptedBytes = cipher.doFinal(plaintextBytes);
              return Base64.getUrlEncoder().withoutPadding().encodeToString(encryptedBytes);

          } catch (Exception e) {
              throw new RuntimeException("Encryption failed: " + e.getMessage(), e);
          }
      }
  }
  ```

  ```python Python theme={null}
  from cryptography.hazmat.primitives.ciphers.aead import AESGCM
  import base64

  def encrypt_payload(json_payload, key, iv):
      """
      Encrypt JSON payload using AES-256-GCM

      Args:
          json_payload (str): JSON string to encrypt
          key (str): Base64 encoded AES key
          iv (str): Base64 encoded IV

      Returns:
          str: Base64URL encoded ciphertext
      """
      try:
          # Decode key and IV
          encryption_key = base64.b64decode(key)
          encryption_iv = base64.b64decode(iv)

          # Convert JSON to bytes
          plaintext_bytes = json_payload.encode('utf-8')

          # Encrypt using AES-GCM
          aesgcm = AESGCM(encryption_key)
          encrypted_bytes = aesgcm.encrypt(encryption_iv, plaintext_bytes, None)

          # Return Base64URL encoded result
          return base64.urlsafe_b64encode(encrypted_bytes).decode('ascii').rstrip('=')

      except Exception as e:
          raise Exception(f"Encryption failed: {str(e)}")
  ```

  ```javascript Node.js theme={null}
  const crypto = require('crypto');

  function encryptPayload(jsonPayload, key, iv) {
      try {
          // Decode Base64 encoded key and IV
          const encryptionKey = Buffer.from(key, 'base64');
          const encryptionIv = Buffer.from(iv, 'base64');

          // Create cipher
          const cipher = crypto.createCipherGCM('aes-256-gcm');
          cipher.setIVLength(encryptionIv.length);

          // Encrypt
          let encrypted = cipher.update(jsonPayload, 'utf8');
          encrypted = Buffer.concat([encrypted, cipher.final()]);

          // Get authentication tag
          const authTag = cipher.getAuthTag();

          // Combine encrypted data and auth tag
          const result = Buffer.concat([encrypted, authTag]);

          // Return Base64URL encoded without padding
          return result.toString('base64url');

      } catch (error) {
          throw new Error(`Encryption failed: ${error.message}`);
      }
  }
  ```
</CodeGroup>

### Decryption (Client-side)

<CodeGroup>
  ```java Java theme={null}
  import javax.crypto.Cipher;
  import javax.crypto.spec.GCMParameterSpec;
  import javax.crypto.spec.SecretKeySpec;
  import java.util.Base64;

  public class PFMDecryption {

      public static String decryptResponse(String ciphertext, String key, String iv) {
          try {
              // Decode the Base64 encoded key and IV
              byte[] encryptionKey = Base64.getDecoder().decode(key);
              byte[] encryptionIv = Base64.getDecoder().decode(iv);

              // Decode the encrypted response
              byte[] encryptedBytes = Base64.getUrlDecoder().decode(ciphertext);

              // Setup AES-GCM decryption
              SecretKeySpec keySpec = new SecretKeySpec(encryptionKey, "AES");
              GCMParameterSpec gcmSpec = new GCMParameterSpec(128, encryptionIv);

              Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
              cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmSpec);

              // Decrypt and return
              byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
              return new String(decryptedBytes, "UTF-8");

          } catch (javax.crypto.AEADBadTagException e) {
              throw new RuntimeException("Authentication tag verification failed! Wrong key, IV, or corrupted data.", e);
          } catch (IllegalArgumentException e) {
              throw new RuntimeException("Invalid Base64URL format in ciphertext.", e);
          } catch (Exception e) {
              throw new RuntimeException("Decryption failed: " + e.getMessage(), e);
          }
      }
  }
  ```

  ```python Python theme={null}
  from cryptography.hazmat.primitives.ciphers.aead import AESGCM
  import base64

  def decrypt_response(ciphertext, key, iv):
      """
      Decrypt response using AES-256-GCM

      Args:
          ciphertext (str): Base64URL encoded encrypted data
          key (str): Base64 encoded AES key
          iv (str): Base64 encoded IV

      Returns:
          str: Decrypted JSON string
      """
      try:
          # Decode key and IV
          encryption_key = base64.b64decode(key)
          encryption_iv = base64.b64decode(iv)

          # Add padding if needed and decode ciphertext
          padding = 4 - len(ciphertext) % 4
          if padding != 4:
              ciphertext += '=' * padding
          encrypted_bytes = base64.urlsafe_b64decode(ciphertext)

          # Decrypt using AES-GCM
          aesgcm = AESGCM(encryption_key)
          decrypted_bytes = aesgcm.decrypt(encryption_iv, encrypted_bytes, None)

          return decrypted_bytes.decode('utf-8')

      except Exception as e:
          if "InvalidTag" in str(e):
              raise Exception("Authentication tag verification failed! Wrong key, IV, or corrupted data.")
          raise Exception(f"Decryption failed: {str(e)}")
  ```

  ```javascript Node.js theme={null}
  const crypto = require('crypto');

  function decryptResponse(ciphertext, key, iv) {
      try {
          // Decode Base64 encoded key and IV
          const encryptionKey = Buffer.from(key, 'base64');
          const encryptionIv = Buffer.from(iv, 'base64');

          // Decode ciphertext
          const encryptedData = Buffer.from(ciphertext, 'base64url');

          // Split encrypted data and auth tag (last 16 bytes)
          const authTag = encryptedData.slice(-16);
          const encrypted = encryptedData.slice(0, -16);

          // Create decipher
          const decipher = crypto.createDecipherGCM('aes-256-gcm');
          decipher.setIVLength(encryptionIv.length);
          decipher.setAuthTag(authTag);

          // Decrypt
          let decrypted = decipher.update(encrypted, null, 'utf8');
          decrypted += decipher.final('utf8');

          return decrypted;

      } catch (error) {
          if (error.message.includes('bad decrypt')) {
              throw new Error('Authentication tag verification failed! Wrong key, IV, or corrupted data.');
          }
          throw new Error(`Decryption failed: ${error.message}`);
      }
  }
  ```
</CodeGroup>

## Security Best Practices

### Key Management

* Keys are generated using cryptographically secure random number generators
* Regular key rotation is recommended
* Keys should be stored securely and never logged or transmitted in plain text
* Client can place a request with us to generate new keys

### Implementation Guidelines

* Always validate the authentication tag during decryption
* Use proper error handling to avoid information leakage
* Implement secure key storage mechanisms
