tls_inspector 0.0.2
tls_inspector: ^0.0.2 copied to clipboard
Inspect a server's TLS certificate: issuer, validity dates, days until expiry, subject alternative names, SHA-1 fingerprint, and trust status.
tls_inspector #
See the TLS certificate a server actually presents: who issued it, when it expires, which names it covers, and whether your platform trusts it. Useful for certificate expiry alerts, deployment checks, and debugging HTTPS errors.
final certificate = await inspectTls('google.com');
print(certificate.issuer); // /C=US/O=Google Trust Services/CN=WR2
print(certificate.daysUntilExpiry()); // e.g. 58
print(certificate.subjectAltNames); // [*.google.com, google.com, ...]
print(certificate.trusted); // true
Platform support #
| Platform | inspectTls |
parseSubjectAltNames |
|---|---|---|
| Android, iOS, Windows, macOS, Linux, Dart VM | Yes | Yes |
| Web | No, browsers do not expose raw TLS connections | Yes |
On the web, inspectTls throws an UnsupportedError. Apps need network
access: the INTERNET permission on Android release builds and the
com.apple.security.network.client entitlement on macOS.
Features #
- Returns the certificate even when it is expired, self-signed, or issued for
another host, with
trustedtelling whether the platform accepted it. - Subject, issuer, validity dates in UTC, days until expiry, SHA-1 fingerprint, and PEM.
- Subject alternative names (DNS names and IP addresses) parsed from the
certificate, which
dart:iodoes not expose. - Stable error codes:
timeout,connect_failed, andhandshake_failed. coversHostchecks a host name against the certificate's names, including wildcards, so you can tell a name mismatch from an untrusted chain.derholds the raw certificate for other fingerprints such as SHA-256.- No dependencies.
Installation #
dependencies:
tls_inspector: ^0.0.2
Usage #
try {
final certificate = await inspectTls(
'example.com',
port: 443,
timeout: const Duration(seconds: 5),
);
if (!certificate.trusted) {
print('Untrusted certificate from ${certificate.issuer}');
} else if (certificate.daysUntilExpiry() < 14) {
print('Renew soon: ${certificate.notAfter}');
}
} on TlsInspectException catch (error) {
print('${error.code}: $error');
}
Parse names from a certificate you already have, on any platform:
final der = base64.decode(
pem.replaceAll(RegExp(r'-----[^-]+-----|\s'), ''),
);
print(parseSubjectAltNames(der));
Tell a name mismatch from an untrusted chain:
final certificate = await inspectTls('wrong.host.badssl.com');
if (!certificate.trusted && !certificate.coversHost('wrong.host.badssl.com')) {
print('Issued for ${certificate.subjectAltNames}'); // [*.badssl.com, badssl.com]
}
Compute a SHA-256 fingerprint with package:crypto:
import 'package:crypto/crypto.dart';
print(sha256.convert(certificate.der));
Limitations #
- Only the server (leaf) certificate is returned.
dart:iodoes not expose the rest of the chain. trustedreflects the trust store of the device running the code, so it can differ between platforms.- The SHA-1 fingerprint identifies a certificate; it says nothing about the signature algorithm.
Flutter example #
FutureBuilder<TlsCertificateInfo>(
future: inspectTls('seungpyo.online'),
builder: (context, snapshot) {
final certificate = snapshot.data;
if (certificate == null) return const LinearProgressIndicator();
return ListTile(
leading: Icon(certificate.trusted ? Icons.lock : Icons.lock_open),
title: Text(certificate.issuer),
subtitle: Text('Expires in ${certificate.daysUntilExpiry()} days'),
);
},
)