FCG Network Interceptor (fcg_network_interceptor)

A Dio interceptor that automatically encrypts request bodies using sodium_libs (ChaCha20-Poly1305).

Features

  • Automatic Encryption: Intercepts POST, PUT, and PATCH requests and automatically encrypts the JSON body.
  • Request Wrapping: Wraps the encrypted string in a standardized JSON structure: {"request": "ENCRYPTED_STRING"}.
  • Selective Encryption: Provides a mechanism to skip encryption for specific requests (e.g., standard application/x-www-form-urlencoded submissions).
  • Error Handling: Catches encryption errors and wraps them in DioException for consistent error handling.

Installation

Add the following to your pubspec.yaml:

dependencies:
  fcg_network_interceptor: ^0.0.3

Usage

1. Initialization

Add the EncryptionInterceptor to your Dio instance. You must provide a base64-encoded key.

import 'package:dio/dio.dart';
import 'package:fcg_network_interceptor/fcg_network_interceptor.dart';

void main() {
  final dio = Dio();
  
  // Create a 32-byte key, base64 encoded
  const myBase64Key = 'YOUR_BASE64_ENCODED_32_BYTE_KEY';

  // Add the interceptor to the chain
  dio.interceptors.add(EncryptionInterceptor(base64Key: myBase64Key));
}

2. Making Encrypted Requests

By default, any POST, PUT, or PATCH request with a JSON body (Map<String, dynamic>) will be encrypted.

// This request body will be automatically encrypted
final response = await dio.post(
  '/api/secure-endpoint',
  data: {
    'userId': '12345',
    'action': 'update_profile'
  },
);

What happens over the network: The body sent to the server will look like:

{
  "request": "U2FsdGVkX1+..."
}

3. Skipping Encryption

If you need to send a request without encryption (e.g., for application/x-www-form-urlencoded or public endpoints), use the skipEncryption option in extra.

final response = await dio.post(
  '/api/public-endpoint',
  data: {
    'grant_type': 'password',
    'username': 'user',
    'password': 'password'
  },
  options: Options(
    contentType: Headers.formUrlEncodedContentType,
    extra: {
      'skipEncryption': true, // Disables the interceptor for this request
    },
  ),
);

4. Double Encryption

You can request specific keys in the request body to be encrypted individually before the entire body is encrypted. This is useful for sensitive fields like PII.

To do this, provide a list of keys in extra['encryptKeys'].

final response = await dio.post(
  '/api/sensitive-action',
  data: {
    'MrNo': '1234',
    'phone': '234124',
    'email': 'test@example.com',
    'Gender': 'male'
  },
  options: Options(
    extra: {
      'encryptKeys': ['MrNo', 'phone', 'email'], // These keys will be encrypted individually first
    },
  ),
);

What happens:

  1. First Pass: The values for MrNo, phone, and email are encrypted individually.
    • MrNo -> "ENC[1234]"
    • phone -> "ENC[234124]"
    • email -> "ENC[test@example.com]"
    • Gender remains "male"
  2. Second Pass: The entire JSON object (with the now-encrypted values) is serialized to a string and encrypted again.
  3. Final Body: {"request": "FINAL_ENCRYPTED_BLOB"}.

Dependencies

  • dio: A powerful Http client for Dart.
  • sodium_libs: Libsodium for Dart.

License

MIT License. See LICENSE for details.

Copyright (c) 2026 Fakeeh Tech.