quixxi 1.0.0 
quixxi: ^1.0.0 copied to clipboard
Flutter plugin for adding SSL Pinning to application, Prevent copy and paste inside the application, Prevent misuse of APIs using API attestion
Quixxi Plugin #
The Flutter plugin provides the following security enhancements for mobile applications:
SSL Pinning #
- 
Ensures secure communication between the application and backend servers by validating the server certificate against a pinned public key.
 - 
Protects against man-in-the-middle (MITM) attacks by preventing connections to unauthorized servers.
 
Clipboard Protection #
- 
Prevents copy and paste actions inside the application to safeguard sensitive information such as passwords, tokens, or personal data.
 - 
Reduces the risk of data leakage through clipboard monitoring or malicious apps.
 
API Attestation #
- 
Protects backend APIs from misuse by validating requests through Secure HashKey attestation.
 - 
Ensures that only genuine, untampered applications can communicate with the server.
 - 
Helps prevent unauthorized API calls and mitigates replay or injection attacks.
 
Integration Notes #
Important #
Quixxi Security Shield must be applied after integrating this plugin into your application.
SSL Pinning #
- 
Debug Builds
- 
SSL certificate validation is not enforced.
 - 
This is intentional to simplify development and testing.
 
 - 
 - 
Release Builds
- 
Quixxi Shield must be applied.
 - 
Enforces SSL Pinning and strong runtime protections.
 
 - 
 
API Attestation #
- In Debug Mode, a default hardcoded hash key is used:
 
MNaiMYHqVH3ZLVfGVc4nqFcd7Gf8Avr6JePPUJZYfrCA7A00GiRSFTPC981P7Vpe1gDUh9YQaKEE2ihGp04GfW7EB2HJx8JVkwv5k1fvDhaQNMetvaFACAw70gP61KYK
- 
Use this key only for development and testing.
 - 
In Production Builds, configure and use SecureHash Key generated on Quixxi portal to protect against API misuse.
 
Getting Started #
Add quixxi as a dependency in your pubspec.yaml:
dependencies:
  quixxi: 1.0.0
Usage example #
SSL Pinning #
Using Dio
import 'package:quixxi/services.dart';
Dio dioClient = getDioClient('https://gorest.co.in',enableSSLPinning: true);
void apiCall() async {
    var header = {'Content-type': 'application/json; charset=utf-8'};
    try {
      final response = await dio.get("https://yourdomain.com/yourapi",
          options: Options(headers: header));
      if (response.statusCode == 200) {
        apiResponse.value = response.data.toString();
      } else {
        print('${response.statusCode} : ${response.data.toString()}');
        apiResponse.value = response.data.toString();
      }
    } catch (error) {
      apiResponse.value = error.toString();
    }
  }
Using Http
import 'package:quixxi/services.dart';
SecureHttpClient secureHttpClient = getSecureHttpClient(enableSSLPinning: true);
void apiCall2() async{
     var header = {'Content-type': 'application/json; charset=utf-8'};
    try {
        Uri uri = Uri.parse("https://gorest.co.in/public/v2/todos");
        final response = await secureHttpClient.get(uri, headers: header);
        if (response.statusCode == 200) {
          apiResponse.value = response.body.toString();
        }else{
            print('${response.statusCode} : ${response.body.toString()}');
            apiResponse.value = response.body.toString();
        }
    } catch (error) {
      apiResponse.value = error.toString();
    }
}
Custom Implementation
import 'package:quixxi/services.dart';
Future myCustomImplementation(String url, Map<String,String> headers) async {
  try{
    final secure = await SSLCertificatePinning().check(
      serverURL: url,
      headerHttp: headers,
      timeout : 50
    );
    if(secure.contains("CONNECTION_SECURE")){
      return true;
    }else{
      return false;
    }
  }catch(e){
    return false;
  }
}
API Attestation #
You can enable API Attestation to automatically send a secure hash (from Quixxi) either in the request header or payload.
With SSLPinning
Using Dio
import 'package:quixxi/services.dart';
// Enable App Attestation and configure hash injection
Dio dioClient = getDioClient(
  'https://gorest.co.in',
  enableSSLPinning: true,
  enableAppAttestation: true,
  sendHashInHeader: true,   // or false
  sendHashInPayload: false, // or true
);
void apicall_dio_app_attestation() async {
  var header = {'Content-type': 'application/json; charset=utf-8'};
  try {
    final response = await dioClient.get(
      urlTextEditingController.text,
      options: Options(headers: header),
    );
    apiResponse.value = response.data.toString();
  } catch (error) {
    apiResponse.value = error.toString();
  }
}
Using Http
import 'package:quixxi/services.dart';
SecureHttpClient secureHttpClient = getSecureHttpClient(
  enableSSLPinning: true,
  enableAppAttestation: true,
  sendHashInPayload: true, // or sendHashInHeader: true
);
void apicall_http_app_attestation() async {
  var header = {'Content-type': 'application/json; charset=utf-8'};
  try {
    Uri uri = Uri.parse(urlTextEditingController.text);
    final response = await secureHttpClient.get(uri, headers: header);
    apiResponse.value = response.body.toString();
  } catch (error) {
    apiResponse.value = error.toString();
  }
}
Without SSLPinning
Same usage, but dont pass enableSSLPinning. it is set to false by default.
SOAP API Support
App Attestation also works with SOAP requests. Just set "Content-Type": "text/xml; charset=utf-8" in headers and provide your envelope.
Using Dio
String soapEnvelope({String? bodyContent}) => '''
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    ${bodyContent ?? ''}
  </soap:Body>
</soap:Envelope>
''';
// Enable App Attestation and configure hash injection
Dio dioClient = getDioClient(
  'https://httpbin.org',
  enableAppAttestation: true,
  sendHashInHeader: true,   // or false
  sendHashInPayload: false, // or true
);
void apicall_dio_soap_with_header() async {
  try {
    isLoading.value = true;
    String envelope = soapEnvelope(bodyContent: '<Test>Hello</Test>');
    final response = await dioClient.post(
      "https://httpbin.org/post",
      data: envelope,
      options: Options(
        headers: {
          'Content-Type': 'text/xml; charset=utf-8',
          'SOAPAction': 'urn:TestAction'
        },
      ),
    );
    isLoading.value = false;
    apiResponse.value = response.data.toString();
  } catch (error) {
    isLoading.value = false;
    apiResponse.value = error.toString();
  }
}
Using Http
  String soapEnvelope({String? bodyContent}) => '''
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    ${bodyContent ?? ''}
  </soap:Body>
</soap:Envelope>
''';
// Enable App Attestation and configure hash injection
SecureHttpClient secureHttpClient = getSecureHttpClient(
  enableAppAttestation: true,
  sendHashInPayload: true, // or sendHashInHeader: true
);
void apicall_http_soap_with_payload() async {
  try {
    isLoading.value = true;
    // Inject SecureHash inside <soap:Body>
    String envelope = soapEnvelope(
      bodyContent: '<Test>Hello</Test>',
    );
    Uri uri = Uri.parse("${urlTextEditingController.text}/post");
    final response = await secureHttpClientWithHashInPayload.post(
      uri,
      headers: {
        'Content-Type': 'text/xml; charset=utf-8',
        'SOAPAction': 'urn:TestAction',
      },
      body: envelope,
    );
    isLoading.value = false;
    apiResponse.value = response.body;
  } catch (error) {
    isLoading.value = false;
    apiResponse.value = error.toString();
  }
}
Copy & Paste Prevention #
Secure Text Field
import 'package:flutter/material.dart';
import 'package:quixxi/text_field/quixxi_text_form_field.dart';
class ExamplePage extends StatelessWidget {
  const ExamplePage({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Quixxi Example')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text('Quixxi Textfield'),
            Container(
              padding: const EdgeInsets.symmetric(vertical: 15),
              Container(
                padding: const EdgeInsets.symmetric(vertical: 15),
                child: QuixxiTextField(
                  decoration: const InputDecoration(
                    border: UnderlineInputBorder(),
                    hintText: 'https://yourdomain.com',
                  ),
                  keyboardType: TextInputType.url,
                  textInputAction: TextInputAction.next,
                  controller: TextEditingController(
                          text: "https://yourdomain.com"),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
Secure Text Form Field
import 'package:flutter/material.dart';
import 'package:your_package/quixxi_text_form_field.dart'; // adjust the import
class ExamplePage extends StatelessWidget {
  const ExamplePage({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Quixxi Example')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text('Quixxi TextFormfield'),
            Container(
              padding: const EdgeInsets.symmetric(vertical: 15),
              child: QuixxiTextFormField(
                decoration: const InputDecoration(
                  border: UnderlineInputBorder(),
                  hintText: 'https://yourdomain.com',
                ),
                keyboardType: TextInputType.url,
                textInputAction: TextInputAction.next,
                controller: TextEditingController(
                  text: "https://yourdomain.com",
                ),
                onSaved: (value) {},
                validator: (value) {},
              ),
            ),
          ],
        ),
      ),
    );
  }
}
Configuration Parameters #
When creating a Dio client with getDioClient or an Http client with getSecureHttpClient, you can configure the following options:
| Parameter | Type | Default | Description | 
|---|---|---|---|
enableSSLPinning | 
bool | 
false | 
Enables SSL certificate pinning (requires Quixxi Shield in release build). | 
enableAppAttestation | 
bool | 
false | 
Enables App Attestation, which sends a secure hash from Quixxi. | 
sendHashInHeader | 
bool | 
false | 
If true, the secure hash is sent in the HTTP/SOAP headers. | 
sendHashInPayload | 
bool | 
false | 
If true, the secure hash is injected into the request payload (JSON or SOAP <soap:Body>). | 
baseUrl (Dio only) | 
String | 
— | Base URL for all API calls made with Dio client. | 
Adding Quixxi Shield to application #
- Create an account in https://portal.quixxi.com
 - Create application container in your account.
 - Upload your application to portal for app protection.
 - For SSL Pinning, choose the option SSL certificate validation via SSLPinning in Shield configuration
 - For API Attestation, choose the option API attestation in Shield configuration
 - After applying shield configurations, wait for Shielding to complete
 - Download protected application from portal.