如何在 Flutter/Dart 中手动验证 x509 证书上的签名
How to manually verify signatures on x509 certificates in Flutter/Dart
我有两个 .pem
格式的 X509Certificate 对象 x1(root) 和 x2。
我想验证 x2 是否由 x1 手动签名。
如何在 Flutter/Dart 中做到这一点?
我找到了这个 article,但是那里的所有操作都是在终端中用 openssl
完成的,在某些阶段需要将 .pem
转换为 .der
以进行提取来自证书的签名。
我也知道 C# 有这样的 method 用于验证,我在 flutter/dart
中找不到任何模拟
我正在使用来自 pub.dev 的 x509b 包来执行此操作。原来的 x509 包似乎不再更新,使用的是过时版本的 asn1lib。在我的版本中,我同时使用 x509 和 asn1lib 本身。很确定有 cleaner/more 高效的方法,但这对我有用。
我还直接使用从我的根证书中提取的 public 密钥,而不是使用整个证书,但我相信您也可以使用这些库执行该步骤。
x509 库中的 tbsCertificate 属性 似乎有误,因此我使用 ASN1Parser 手动提取了 TBS 证书部分。
decodePEM 函数取自 asn1lib 存储库中的示例。
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));
}
我有两个 .pem
格式的 X509Certificate 对象 x1(root) 和 x2。
我想验证 x2 是否由 x1 手动签名。
如何在 Flutter/Dart 中做到这一点?
我找到了这个 article,但是那里的所有操作都是在终端中用 openssl
完成的,在某些阶段需要将 .pem
转换为 .der
以进行提取来自证书的签名。
我也知道 C# 有这样的 method 用于验证,我在 flutter/dart
中找不到任何模拟我正在使用来自 pub.dev 的 x509b 包来执行此操作。原来的 x509 包似乎不再更新,使用的是过时版本的 asn1lib。在我的版本中,我同时使用 x509 和 asn1lib 本身。很确定有 cleaner/more 高效的方法,但这对我有用。
我还直接使用从我的根证书中提取的 public 密钥,而不是使用整个证书,但我相信您也可以使用这些库执行该步骤。
x509 库中的 tbsCertificate 属性 似乎有误,因此我使用 ASN1Parser 手动提取了 TBS 证书部分。
decodePEM 函数取自 asn1lib 存储库中的示例。
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));
}