crosspki 3.0.0
crosspki: ^3.0.0 copied to clipboard
Flutter plugin for handling X509 certificates and key pairs from native platform key stores.
example/lib/main.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:crosspki/crosspki.dart';
import 'package:crosspki_example/sample_pkcs12.dart';
import 'package:crosspki_example/test_ca.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
runCrossPkiApis();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> runCrossPkiApis() async {
try {
print('LISTING CERTIFICATES');
var certs = await CrossPki.listCertificatesWithKey();
print('Certs count: ${certs.length}');
print('IMPORTING PKCS#12');
await CrossPki.importPkcs12(samplePkcs12, samplePkcs12Password);
// Only what this import added: the device may hold certificates of its own, and the demo must
// leave them alone.
final imported = _added(certs, await CrossPki.listCertificatesWithKey());
if (imported.isEmpty) {
print('Nothing new listed: the PKCS#12 certificate was already on the device');
} else {
final userCertificate = imported.first;
print('Imported: ${userCertificate.subjectName}');
print('CPF: ${userCertificate.pkiBrazil.cpfFormatted}');
print('SIGN DATA TEST');
var sig = await CrossPki.signData(userCertificate.thumbprint,
DigestAlgorithm.sha256, base64Decode('SGVsbG8sIFdvcmxkIQ=='));
print('Signature: ${base64Encode(sig.toList())}');
print('SIGN HASH TEST');
sig = await CrossPki.signHash(
userCertificate.thumbprint,
DigestAlgorithm.sha256,
base64Decode('3/1gIbsr1bCvZ2KQgJ7DpTGR3YHH9wpLKGiKNiGCmG8='));
print('Signature: ${base64Encode(sig.toList())}');
for (final certificate in imported) {
await CrossPki.removeCertificate(certificate.thumbprint);
}
print('Removed');
certs = await CrossPki.listCertificatesWithKey();
print('Certs count: ${certs.length}');
}
print('GENERATING RSA KEY PAIR...');
var keyPair = await CrossPki.generateRsaKeyPair(2048);
print('keyId: ${keyPair.keyId}');
print(
'publicKey ${keyPair.algorithm}: ${base64Encode(keyPair.publicKeyEncoded.toList())}');
print('GENERATING CSR...');
var csr = await CrossPki.generateCsr(keyPair);
print('CSR: ${base64Encode(csr.toList())}');
print('ISSUING CERTIFICATE ON THE TEST CA...');
final issued = await TestCa.issueCertificate(csr);
print('IMPORTING ISSUED CERTIFICATE');
final issuedCertificate =
await CrossPki.importCertificate(issued, keyPair.keyId);
print('Imported: ${issuedCertificate.subjectName}');
print('SIGN HASH WITH ISSUED CERTIFICATE');
final issuedSig = await CrossPki.signHash(
issuedCertificate.thumbprint,
DigestAlgorithm.sha256,
base64Decode('3/1gIbsr1bCvZ2KQgJ7DpTGR3YHH9wpLKGiKNiGCmG8='));
print('Signature: ${base64Encode(issuedSig.toList())}');
// Removing the certificate removes its key with it.
await CrossPki.removeCertificate(issuedCertificate.thumbprint);
print('Removed');
print('DONE');
} catch (ex) {
print('ERROR: $ex');
}
}
/// The certificates in [after] that are not in [before], counting duplicates: importing a
/// certificate the device already holds may list it twice.
static List<PKCertificate> _added(
List<PKCertificate> before, List<PKCertificate> after) {
final remaining = <String, int>{};
for (final certificate in before) {
remaining.update(certificate.thumbprint, (count) => count + 1,
ifAbsent: () => 1);
}
final added = <PKCertificate>[];
for (final certificate in after) {
final count = remaining[certificate.thumbprint] ?? 0;
if (count > 0) {
remaining[certificate.thumbprint] = count - 1;
} else {
added.add(certificate);
}
}
return added;
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Cross PKI Plugin example app'),
),
body: const Center(
child: Text('Running Cross PKI API'),
),
),
);
}
}