How to manually verify signatures on x509 certificates in Flutter/Dart
I am doing this using x509b package from pub.dev. The original x509 package is seemingly not updated anymore and uses an outdated version of asn1lib. In my version I am using both x509 and asn1lib itself. Pretty sure there are cleaner/more performant ways, but this does the trick for me.
I also use the extracted public key from my root certificate directly instead of using the entire certificate, but I am sure you can also do that step with these libraries.
The tbsCertificate property from x509 library seems wrong, so I extract the TBS Certificate part manually using ASN1Parser.
The decodePEM function was taken from the example in asn1lib repo.
import 'dart:convert';
import 'dart:typed_data';
import 'package:x509b/x509.dart' as x509;
import 'package:asn1lib/asn1lib.dart';
bool verifyCertificate() {
var strX1PublicKeyInfo = "-----BEGIN PUBLIC KEY-----\nSOME PUBLIC KEY\n-----END PUBLIC KEY-----";
var strX2Certificate = "-----BEGIN CERTIFICATE-----\nSOME CERTIFICATE\n-----END CERTIFICATE-----";
var x1PublicKey = (x509.parsePem(strX1PublicKeyInfo).single as x509.SubjectPublicKeyInfo).subjectPublicKey as x509.RsaPublicKey;
var x2Certificate = x509.parsePem(strX2Certificate).single as x509.X509Certificate;
var x2CertificateDER = decodePEM(strX2Certificate);
var asn1Parser = ASN1Parser(x2CertificateDER);
var seq = asn1Parser.nextObject() as ASN1Sequence;
var tbsSequence = seq.elements[0] as ASN1Sequence;
var signature = x509.Signature(Uint8List.fromList(x2Certificate.signatureValue!));
var verifier = x1PublicKey.createVerifier(x509.algorithms.signing.rsa.sha256);
return verifier.verify(tbsSequence.encodedBytes, signature)
}
Uint8List decodePEM(pem) {
var startsWith = [
'-----BEGIN PUBLIC KEY-----',
'-----BEGIN PRIVATE KEY-----',
'-----BEGIN CERTIFICATE-----',
];
var endsWith = [
'-----END PUBLIC KEY-----',
'-----END PRIVATE KEY-----',
'-----END CERTIFICATE-----'
];
//HACK
for (var s in startsWith) {
if (pem.startsWith(s)) pem = pem.substring(s.length);
}
for (var s in endsWith) {
if (pem.endsWith(s)) pem = pem.substring(0, pem.length - s.length);
}
//Dart base64 decoder does not support line breaks
pem = pem.replaceAll('\n', '');
pem = pem.replaceAll('\r', '');
return Uint8List.fromList(base64.decode(pem));
}
Eugene Alitz
Updated on December 25, 2022Comments
-
Eugene Alitz over 1 year
I have two X509Certificate objects x1(root) and x2 in
.pem
format.I want to verify that x2 was signed by x1 manually.
How to exactly do this in Flutter/Dart?
I found this article, but all operations there is done in terminal with
openssl
and at some stage there is need to convert.pem
to.der
for extracting of signature from the certificate.Also i know that C# have such methodfor verifying and i cannot find any analog in the flutter/dart
-
Marco7757 over 2 yearsDid you ever find an answer to this problem?
-