TrustPin SDK for Flutter
A comprehensive Flutter plugin for TrustPin SSL certificate pinning that provides robust security against man-in-the-middle (MITM) attacks by validating server certificates against pre-configured public key pins.
🌐 Get started at TrustPin.cloud | 🎯 Manage your certificates in the Cloud Console
📋 Table of Contents
- Features
- Installation
- Platform Setup
- Quick Start
- Advanced Usage
- API Documentation
- Example
- Security Considerations
- Platform-Specific Implementation
- Security Best Practices
- Performance Considerations
- Testing
- Example App
- Migration Guide
- Contributing
- License
- Support & Community
🚀 Features
- 🔒 SSL Certificate Pinning: Advanced certificate validation using SHA-256/SHA-512 public key pins
- 📋 JWS-based Configuration: Securely fetch signed pinning configurations from TrustPin CDN
- 🌐 Cross-platform Support: Native implementations for iOS (Swift), Android (Kotlin), and macOS (Swift)
- ⚙️ Flexible Pinning Modes: Support for strict (production) and permissive (development) validation modes
- 🔧 Comprehensive Error Handling: Detailed error types with programmatic checking capabilities
- 📊 Configurable Logging: Multiple log levels for debugging, monitoring, and production use
- 🛡️ Thread Safety: Built with Flutter's async/await pattern and native concurrency models
- ⚡ Intelligent Caching: 10-minute configuration caching with stale fallback for performance
- 🔐 ECDSA P-256 Signature Verification: Cryptographic validation of configuration integrity
- 🚀 HTTP Client Integration: Built-in interceptors for popular HTTP clients (http, Dio)
📦 Installation
Using pub.dev (Recommended)
Add TrustPin SDK to your pubspec.yaml:
dependencies:
trustpin_sdk: ^latest
Then install the package:
flutter pub get
🛠️ Platform Setup
iOS Requirements
- Minimum iOS Version: 13.0+
- Xcode: 15.0+
- Swift: 5.0+
- Native Dependencies: TrustPin Swift SDK (automatically configured)
The iOS implementation uses the native TrustPin Swift SDK which is automatically linked via CocoaPods. No additional configuration required.
macOS Requirements
- Minimum macOS Version: 13.0+
- Xcode: 15.0+
- Swift: 5.0+
- Native Dependencies: TrustPin Swift SDK (automatically configured)
The macOS implementation uses the same native TrustPin Swift SDK as iOS, automatically linked via CocoaPods. Requires network client entitlement for sandbox apps.
Android Requirements
- Minimum SDK: API 25 (Android 5.0)+
- Target SDK: API 34+ (recommended)
- Kotlin: 2.3.0+
- Native Dependencies: TrustPin Kotlin SDK (automatically configured)
The Android implementation uses the native TrustPin Kotlin SDK which is automatically included via Gradle. No additional configuration required.
Network Permissions
The SDK requires network access to fetch pinning configurations. Ensure your app has proper network permissions:
Android
The plugin automatically includes the required network permission in its AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
iOS
Network access is enabled by default. For apps targeting iOS 14+, ensure your Info.plist allows network access to cdn.trustpin.cloud:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSExceptionDomains</key>
<dict>
<key>cdn.trustpin.cloud</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<false/>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.2</string>
</dict>
</dict>
</dict>
macOS
For sandboxed macOS apps, add the network client entitlement to your entitlements files:
<!-- In DebugProfile.entitlements and Release.entitlements -->
<key>com.apple.security.network.client</key>
<true/>
For non-sandboxed apps, network access is enabled by default.
🚀 Quick Start
1. Get Your Credentials
First, sign up at TrustPin Cloud Console and create a project to get your:
- Organization ID
- Project ID
- Public Key (ECDSA P-256, Base64-encoded)
2. Initialize the SDK
import 'package:trustpin_sdk/trustpin_sdk.dart';
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
_initializeTrustPin();
}
Future<void> _initializeTrustPin() async {
try {
// Set debug logging for development
await TrustPin.setLogLevel(TrustPinLogLevel.debug);
// Initialize with your credentials
await TrustPin.setup(
organizationId: 'your-org-id',
projectId: 'your-project-id',
publicKey: 'LS0tLS1CRUdJTi...', // Your Base64 public key
mode: TrustPinMode.strict, // Use strict mode for production
);
print('TrustPin SDK initialized successfully!');
} catch (e) {
print('Failed to initialize TrustPin: $e');
}
}
3. Verify Certificates
Future<void> verifyServerCertificate() async {
// Example PEM certificate (in practice, you'd get this from your HTTP client)
const pemCertificate = '''
-----BEGIN CERTIFICATE-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7Q1jx8...
-----END CERTIFICATE-----
''';
try {
await TrustPin.verify('api.example.com', pemCertificate);
print('✅ Certificate is valid and matches configured pins!');
} on TrustPinException catch (e) {
print('❌ Certificate verification failed: ${e.code} - ${e.message}');
// Handle specific error types
if (e.isPinsMismatch) {
print('The certificate doesn\'t match any configured pins');
} else if (e.isDomainNotRegistered) {
print('Domain not configured for pinning (strict mode)');
} else if (e.isAllPinsExpired) {
print('All configured pins have expired');
}
} catch (e) {
print('Unexpected error: $e');
}
}
💼 Advanced Usage
Integration with HTTP Clients
Using with Dio
The SDK provides a built-in TrustPinDioInterceptor for seamless Dio integration:
import 'package:dio/dio.dart';
import 'package:trustpin_sdk/trustpin_sdk.dart';
// Create Dio instance with TrustPin certificate validation
final dio = Dio();
dio.interceptors.add(TrustPinDioInterceptor());
// All HTTPS requests will now have certificate pinning validation
try {
final response = await dio.get('https://api.example.com/data');
print('Request successful: ${response.statusCode}');
} on DioException catch (e) {
if (e.error is TrustPinException) {
final trustPinError = e.error as TrustPinException;
print('Certificate pinning failed: ${trustPinError.code} - ${trustPinError.message}');
} else {
print('Request failed: ${e.message}');
}
}
// The interceptor automatically:
// 1. Validates standard TLS certificates (OS-level validation)
// 2. Performs TrustPin certificate pinning validation
// 3. Caches certificates for performance
// 4. Prevents requests with invalid certificates
// Manage certificate cache if needed
final interceptor = TrustPinDioInterceptor();
dio.interceptors.add(interceptor);
// Clear all cached certificates
interceptor.clearCertificateCache();
Using with http package
The SDK provides a built-in TrustPinHttpClient that wraps the standard http.Client:
import 'package:http/http.dart' as http;
import 'package:trustpin_sdk/trustpin_sdk.dart';
// Create a TrustPin-enabled HTTP client
final httpClient = TrustPinHttpClient.create();
// Or wrap an existing client
final customClient = http.Client();
final httpClient = TrustPinHttpClient(customClient);
// Use it like a normal http.Client
final response = await httpClient.get(Uri.parse('https://api.example.com/data'));
// The client automatically:
// 1. Validates standard TLS certificates
// 2. Performs TrustPin certificate pinning
// 3. Caches certificates for performance
// Clear certificate cache if needed
httpClient.clearCertificateCache();
// Clean up when done
httpClient.close();
🔒 Secure your Flutter apps with TrustPin SSL Certificate Pinning 🔒