'How to verify certificate chain in Flutter?

I have a mobile app written in Flutter that stores an intermediate cert. Other mobile clients can send certificates to this device and it should decide whether the sent certificate was issued based on the intermediate cert or not. Shortly, I have to verify the integrity of the certificate chain. I implemented a test function in Node.js/TS but I don't know how I can do the same thing in Flutter. Here is the example code:

import fs from "fs";
import nodeForge from "node-forge";


function validateCert(certPem: string) {
  const pki = nodeForge.pki;

  try {
    const caCert = fs.readFileSync("pki_int_ca.pem", { encoding: "utf-8" });
    const caStore = pki.createCaStore([caCert]);

    const certToVerify = pki.certificateFromPem(certPem);

    const verified = pki.verifyCertificateChain(caStore, [certToVerify]);
    console.log("Certificate Verified: " + verified);
  } catch (err) {
    console.log(err);
  }
}



Solution 1:[1]

I am using this library https://github.com/jeroentrappers/x509 to verify certificate chain in flutter.

here is my code:

import 'dart:convert';
import 'dart:typed_data';
import 'package:x509b/x509.dart' as x509;
import 'package:asn1lib/asn1lib.dart';

import 'flutter_log.dart';
 //caCert is the root certificate. and serverCert is the certificate need to be verifed
 bool verifyCertificate(String caCert, String serverCert) {
  // 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(caCert).single as x509.X509Certificate).publicKey as x509.RsaPublicKey;
  var x2Certificate = x509.parsePem(serverCert).single as x509.X509Certificate;

  var x2CertificateDER = decodePEM(serverCert);

  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(String pem) {
  var startsWith = [
    '-----BEGIN PUBLIC KEY-----',
    '-----BEGIN PRIVATE KEY-----',
    '-----BEGIN CERTIFICATE-----',
  ];
  var endsWith = [
    '-----END PUBLIC KEY-----',
    '-----END PRIVATE KEY-----',
    '-----END CERTIFICATE-----'
  ];
  pem=pem.trim();
  //HACK
  for (var s in startsWith) {
    if (pem.startsWith(s)) pem = pem.substring(s.length);
  }

  for (var s in endsWith) {
    if (pem.trim().endsWith(s)) {
      Log().i("certificate:substring");
      pem = pem.trim().split(s)[0];
    }
  }

  //Dart base64 decoder does not support line breaks
  pem = pem.replaceAll('\n', '');
  pem = pem.replaceAll('\r', '');
  return Uint8List.fromList(base64.decode(pem));
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 wxkly