trustpin_sdk 1.2.0
trustpin_sdk: ^1.2.0 copied to clipboard
A Flutter plugin for TrustPin SSL certificate pinning SDK that provides enhanced security for network connections by validating SSL certificates against configured pins.
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
Using Git (Development) #
For the latest development version:
dependencies:
trustpin_sdk:
git:
url: https://github.com/trustpin-cloud/trustpin-libraries.git
path: flutter/trustpin_sdk
๐ ๏ธ 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: 1.9.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();
Environment-Specific Configuration #
class TrustPinConfig {
static Future<void> initializeForEnvironment() async {
const environment = String.fromEnvironment('ENVIRONMENT', defaultValue: 'development');
switch (environment) {
case 'production':
await _initializeProduction();
break;
case 'staging':
await _initializeStaging();
break;
default:
await _initializeDevelopment();
}
}
static Future<void> _initializeProduction() async {
await TrustPin.setLogLevel(TrustPinLogLevel.error);
await TrustPin.setup(
organizationId: 'prod-org-123',
projectId: 'prod-project-456',
publicKey: 'LS0tLS1CRUdJTi...', // Production public key
mode: TrustPinMode.strict,
);
}
static Future<void> _initializeStaging() async {
await TrustPin.setLogLevel(TrustPinLogLevel.info);
await TrustPin.setup(
organizationId: 'staging-org-123',
projectId: 'staging-project-456',
publicKey: 'LS0tLS1CRUdJTi...', // Staging public key
mode: TrustPinMode.strict,
);
}
static Future<void> _initializeDevelopment() async {
await TrustPin.setLogLevel(TrustPinLogLevel.debug);
await TrustPin.setup(
organizationId: 'dev-org-123',
projectId: 'dev-project-456',
publicKey: 'LS0tLS1CRUdJTi...', // Development public key
mode: TrustPinMode.permissive, // Allow unpinned domains in development
);
}
}
// Usage in main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await TrustPinConfig.initializeForEnvironment();
runApp(MyApp());
}
Error Handling Patterns #
class TrustPinErrorHandler {
static void handleVerificationError(TrustPinException error, String domain) {
// Log error for monitoring
_logSecurityEvent(error, domain);
switch (error.code) {
case 'PINS_MISMATCH':
_handlePinsMismatch(error, domain);
break;
case 'DOMAIN_NOT_REGISTERED':
_handleDomainNotRegistered(error, domain);
break;
case 'ALL_PINS_EXPIRED':
_handleAllPinsExpired(error, domain);
break;
case 'INVALID_SERVER_CERT':
_handleInvalidCertificate(error, domain);
break;
case 'ERROR_FETCHING_PINNING_INFO':
_handleNetworkError(error, domain);
break;
default:
_handleUnknownError(error, domain);
}
}
static void _handlePinsMismatch(TrustPinException error, String domain) {
// Critical security issue - potential MITM attack
print('๐จ SECURITY ALERT: Certificate mismatch for $domain');
// Consider blocking the request and alerting the user
}
static void _handleDomainNotRegistered(TrustPinException error, String domain) {
print('โ ๏ธ Domain $domain not configured for pinning');
// In strict mode, this might be intentional or an oversight
}
static void _handleAllPinsExpired(TrustPinException error, String domain) {
print('โฐ All pins expired for $domain - update needed');
// Consider allowing the request but log for monitoring
}
static void _handleInvalidCertificate(TrustPinException error, String domain) {
print('โ Invalid certificate format for $domain');
// This might indicate a parsing issue
}
static void _handleNetworkError(TrustPinException error, String domain) {
print('๐ Network error fetching pinning configuration');
// Consider using cached configuration or fallback behavior
}
static void _handleUnknownError(TrustPinException error, String domain) {
print('โ Unknown error for $domain: ${error.message}');
// Log for investigation
}
static void _logSecurityEvent(TrustPinException error, String domain) {
// Send to your security monitoring system
final event = {
'timestamp': DateTime.now().toIso8601String(),
'domain': domain,
'error_code': error.code,
'error_message': error.message,
'app_version': 'your-app-version',
};
// Send to your logging/monitoring service
print('Security event logged: $event');
}
}
// Usage
try {
await TrustPin.verify('api.example.com', certificate);
} on TrustPinException catch (e) {
TrustPinErrorHandler.handleVerificationError(e, 'api.example.com');
// Decide whether to proceed with the request or abort
rethrow; // Re-throw if you want to abort the request
}
๐ API Documentation #
For complete API documentation, visit our GitHub Pages Documentation.
TrustPin Class (Static Methods) #
TrustPin.setup()
Initializes the TrustPin SDK with your project credentials.
static Future<void> setup({
required String organizationId,
required String projectId,
required String publicKey,
Uri? configurationURL, // Optional custom URL for self-hosted configurations
TrustPinMode mode = TrustPinMode.strict,
})
Parameters:
organizationId: Your organization identifier from the TrustPin dashboardprojectId: Your project identifier from the TrustPin dashboardpublicKey: Base64-encoded ECDSA P-256 public key for JWS verificationconfigurationURL: Optional custom URL for self-hosted configurations (null for CDN-managed)mode: Pinning mode (strict or permissive)
Throws: TrustPinException if setup fails
TrustPin.verify()
Verifies a certificate against the configured pins for a domain.
static Future<void> verify(String domain, String certificate)
Parameters:
domain: The domain name to verify (e.g., "api.example.com")certificate: PEM-encoded certificate string with BEGIN/END markers
Throws: TrustPinException if verification fails
TrustPin.setLogLevel()
Sets the logging level for TrustPin SDK.
static Future<void> setLogLevel(TrustPinLogLevel level)
TrustPinHttpClient Class #
A certificate pinning interceptor for the http package that wraps any http.Client.
Constructor
TrustPinHttpClient(http.Client inner)
Factory Constructor
factory TrustPinHttpClient.create()
Creates a TrustPinHttpClient with a default http.Client.
Methods
send(BaseRequest request): Sends HTTP request with certificate validationclearCertificateCache(): Clears the internal certificate cacheclose(): Closes the client and clears resources
TrustPinDioInterceptor Class #
A certificate pinning interceptor for the Dio HTTP client.
Constructor
TrustPinDioInterceptor()
Creates a new interceptor that validates certificates for all HTTPS requests made through Dio.
Methods
onRequest(RequestOptions, RequestInterceptorHandler): Validates certificates before sending requestsclearCertificateCache(): Clears the internal certificate cache
Enums #
TrustPinMode
Pinning modes that control behavior for unregistered domains:
TrustPinMode.strict: Throws errors for unregistered domains (recommended for production)TrustPinMode.permissive: Allows unregistered domains to bypass pinning (development/testing)
TrustPinLogLevel
Log levels for controlling SDK output verbosity:
TrustPinLogLevel.none: No logging outputTrustPinLogLevel.error: Only error messagesTrustPinLogLevel.info: Error and informational messagesTrustPinLogLevel.debug: All messages including debug information
Exception Handling #
TrustPinException
Exception thrown by TrustPin operations with detailed error information:
Properties:
code: Error code identifying the type of errormessage: Human-readable error messagedetails: Additional error details (may be null)
Error Types:
INVALID_PROJECT_CONFIG: Invalid setup parametersERROR_FETCHING_PINNING_INFO: CDN fetch failureINVALID_SERVER_CERT: Invalid certificate formatPINS_MISMATCH: Certificate doesn't match configured pinsALL_PINS_EXPIRED: All configured pins have expiredJWS_VALIDATION_FAILED: JWS signature validation failedDOMAIN_NOT_REGISTERED: Domain not configured (strict mode only)CONFIGURATION_VALIDATION_FAILED: Configuration validation failed
Helper Methods:
// Check specific error types
if (exception.isPinsMismatch) {
// Handle certificate mismatch
}
if (exception.isDomainNotRegistered) {
// Handle unregistered domain in strict mode
}
Example #
See the example/ directory for a complete sample application that demonstrates:
- SDK initialization with credentials
- Certificate verification
- Error handling
- Log level configuration
Security Considerations #
Production Deployment #
- Use Strict Mode: Always use
TrustPinMode.strictin production - Secure Credentials: Never commit credentials to version control
- Minimal Logging: Use
TrustPinLogLevel.errorornonein production - Regular Updates: Keep pinning configurations up to date
Development and Testing #
- Permissive Mode: Use
TrustPinMode.permissivefor development - Debug Logging: Enable
TrustPinLogLevel.debugfor troubleshooting - Test Environment: Use separate credentials for testing
Platform-Specific Implementation #
iOS #
- Uses TrustPin Swift SDK from https://github.com/trustpin-cloud/TrustPin-Swift.binary
- Supports iOS 13.0 and later
- Built with Swift 5.0+
- Async/await support for modern Swift concurrency
macOS #
- Uses TrustPin Swift SDK from https://github.com/trustpin-cloud/TrustPin-Swift.binary
- Supports macOS 13.0 and later
- Built with Swift 5.0+
- Async/await support for modern Swift concurrency
- Sandboxing compatible with proper entitlements
Android #
- Uses TrustPin Kotlin SDK from Maven (
cloud.trustpin:kotlin-sdk:<<version>>) - Supports Android API 21 and later
- Built with Kotlin coroutines
- Multiplatform support (Android/JVM)
๐ Security Best Practices #
Production Checklist #
- โ
Use
TrustPinMode.strictmode - โ
Set log level to
TrustPinLogLevel.errorornone - โ Store credentials securely (not in source code)
- โ Implement proper error handling for certificate failures
- โ Monitor certificate validation errors
- โ Keep pinning configurations up to date
- โ Test certificate validation in staging environment
Development Tips #
- ๐ง Use
TrustPinMode.permissivefor development - ๐ง Enable
TrustPinLogLevel.debugfor troubleshooting - ๐ง Use separate credentials for different environments
- ๐ง Test with both valid and invalid certificates
- ๐ง Verify error handling works correctly
๐ Performance Considerations #
- Configuration Caching: Pinning configurations are cached for 10 minutes
- Network Optimization: Initial setup requires one CDN request
- Memory Usage: Minimal memory footprint with efficient native implementations
- CPU Impact: Certificate validation is highly optimized in native code
- Battery Life: Negligible impact on battery consumption
๐งช Testing #
The plugin includes comprehensive test coverage:
# Run unit tests
flutter test
# Run integration tests (requires device/emulator)
cd example
flutter test integration_test/plugin_integration_test.dart
# Run with coverage
flutter test --coverage
๐ฑ Example App #
The example/ directory contains a complete sample application demonstrating:
- SDK initialization with different configurations
- Certificate verification with various scenarios
- Error handling patterns
- Integration with HTTP clients
- Environment-specific setup
To run the example:
cd example
flutter pub get
flutter run
๐ Migration Guide #
From Direct Native SDK Usage #
If you're currently using the native TrustPin SDKs directly:
-
Replace native SDK imports:
// Remove native imports // iOS: import TrustPinKit // Android: import cloud.trustpin.kotlin.sdk.TrustPin // Add Flutter plugin import 'package:trustpin_sdk/trustpin_sdk.dart'; -
Update initialization:
// Old (iOS) // try await TrustPin.setup(organizationId: "...", projectId: "...", publicKey: "...", mode: .strict) // Old (Android) // val trustPin = TrustPin.create() // trustPin.setup("...", "...", "...") // New (Flutter) - Using static methods await TrustPin.setup( organizationId: 'your-org-id', projectId: 'your-project-id', publicKey: 'your-public-key', mode: TrustPinMode.strict, ); -
Update certificate verification:
// Old (iOS) // try await TrustPin.verify(domain: "api.example.com", certificate: pemCert) // Old (Android) // trustPin.verify("api.example.com", x509Certificate) // New (Flutter) - Using static methods await TrustPin.verify('api.example.com', pemCertificate);
๐ค Contributing #
We welcome contributions! Please see our Contributing Guide for detailed information about:
- Development environment setup
- Code style guidelines
- Testing requirements
- Pull request process
Quick Contribution Steps #
- Fork the repository
- Create feature branch:
git checkout -b feature/amazing-feature - Make changes with tests
- Run quality checks:
dart analyze --fatal-infos dart format --set-exit-if-changed . flutter test - Create pull request with clear description
๐ License #
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Support & Community #
Getting Help #
- ๐ Documentation: GitHub Pages
- ๐ API Reference: pub.dev/documentation/trustpin_sdk
- ๐ Issues: GitHub Issues
- ๐ฌ Discussions: GitHub Discussions
Professional Support #
- ๐ง Email: [email protected]
- ๐ Website: trustpin.cloud
- ๐ Documentation: docs.trustpin.cloud
- ๐ฏ Cloud Console: app.trustpin.cloud
Stay Updated #
- โญ Star this repository to stay updated with releases
- ๐ Watch for important security updates
- ๐ข Follow @TrustPinCloud on Twitter
๐ Secure your Flutter apps with TrustPin SSL Certificate Pinning ๐
Get Started โข Documentation โข Support