From b0c06c614642f82118ebee08b14a172080695beb Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Tue, 16 Jun 2020 00:25:29 +0200 Subject: [PATCH] updated X509Certificate class --- flutter_inappwebview.iml | 1 + lib/src/X509Certificate/asn1_object.dart | 14 ++++ lib/src/X509Certificate/key_usage.dart | 55 ++++++++++++++ lib/src/X509Certificate/main.dart | 1 + lib/src/X509Certificate/oid.dart | 9 ++- lib/src/X509Certificate/x509_certificate.dart | 76 +++++++++++++------ lib/src/X509Certificate/x509_extension.dart | 4 +- 7 files changed, 132 insertions(+), 28 deletions(-) create mode 100644 lib/src/X509Certificate/key_usage.dart diff --git a/flutter_inappwebview.iml b/flutter_inappwebview.iml index c6749d82..e6d1884c 100755 --- a/flutter_inappwebview.iml +++ b/flutter_inappwebview.iml @@ -26,6 +26,7 @@ + diff --git a/lib/src/X509Certificate/asn1_object.dart b/lib/src/X509Certificate/asn1_object.dart index c5ee91b0..77c77789 100644 --- a/lib/src/X509Certificate/asn1_object.dart +++ b/lib/src/X509Certificate/asn1_object.dart @@ -25,6 +25,20 @@ class ASN1Object { return null; } + ASN1Object firstSub() { + if (subCount() > 0) { + return sub.first; + } + return null; + } + + ASN1Object lastSub() { + if (subCount() > 0) { + return sub.last; + } + return null; + } + int subCount() { return sub?.length ?? 0; } diff --git a/lib/src/X509Certificate/key_usage.dart b/lib/src/X509Certificate/key_usage.dart new file mode 100644 index 00000000..d756db3a --- /dev/null +++ b/lib/src/X509Certificate/key_usage.dart @@ -0,0 +1,55 @@ +class KeyUsage { + final int _value; + + const KeyUsage._internal(this._value); + + static List values = [ + KeyUsage.digitalSignature, + KeyUsage.nonRepudiation, + KeyUsage.keyEncipherment, + KeyUsage.dataEncipherment, + KeyUsage.keyAgreement, + KeyUsage.keyCertSign, + KeyUsage.cRLSign, + KeyUsage.encipherOnly, + KeyUsage.decipherOnly, + ]; + + static KeyUsage fromIndex(int value) { + return KeyUsage.values.firstWhere((element) => element.toValue() == value, orElse: () => null); + } + + int toValue() => _value; + + String name() => _KeyUsageMapName[this._value]; + + @override + String toString() => "($_value, ${name()})"; + + static const digitalSignature = const KeyUsage._internal(0); + static const nonRepudiation = const KeyUsage._internal(1); + static const keyEncipherment = const KeyUsage._internal(2); + static const dataEncipherment = const KeyUsage._internal(3); + static const keyAgreement = const KeyUsage._internal(4); + static const keyCertSign = const KeyUsage._internal(5); + static const cRLSign = const KeyUsage._internal(6); + static const encipherOnly = const KeyUsage._internal(7); + static const decipherOnly = const KeyUsage._internal(8); + + bool operator ==(value) => value == _value; + + @override + int get hashCode => _value.hashCode; + + static const Map _KeyUsageMapName = { + 0: "digitalSignature", + 1: "nonRepudiation", + 2: "keyEncipherment", + 3: "dataEncipherment", + 4: "keyAgreement", + 5: "keyCertSign", + 6: "cRLSign", + 7: "encipherOnly", + 8: "decipherOnly", + }; +} diff --git a/lib/src/X509Certificate/main.dart b/lib/src/X509Certificate/main.dart index 0e27305d..2ee58377 100644 --- a/lib/src/X509Certificate/main.dart +++ b/lib/src/X509Certificate/main.dart @@ -3,6 +3,7 @@ export 'asn1_distinguished_names.dart'; export 'asn1_identifier.dart'; export 'asn1_object.dart'; export 'oid.dart'; +export 'key_usage.dart'; export 'x509_certificate.dart'; export 'x509_extension.dart'; export 'x509_public_key.dart'; diff --git a/lib/src/X509Certificate/oid.dart b/lib/src/X509Certificate/oid.dart index 9287cb5d..1f4164f6 100644 --- a/lib/src/X509Certificate/oid.dart +++ b/lib/src/X509Certificate/oid.dart @@ -236,14 +236,15 @@ class OID { "1.2.840.113549.1.1.11": "sha256WithRSAEncryption", "1.2.840.113549.1.1.12": "sha384WithRSAEncryption", "1.2.840.113549.1.1.13": "sha512WithRSAEncryption", - "1.2.840.113549.1.7.1": "data", - "1.2.840.113549.1.7.2": "signedData", + "1.2.840.113549.1.7.1": "pkcs7data", + "1.2.840.113549.1.7.2": "pkcs7signedData", + "1.2.840.113549.1.7.3": "pkcs7envelopedData", "1.2.840.113549.1.9.1": "emailAddress", "1.2.840.113549.1.9.16.2.47": "signingCertificateV2", "1.2.840.113549.1.9.3": "contentType", "1.2.840.113549.1.9.4": "messageDigest", "1.2.840.113549.1.9.5": "signingTime", - "1.2.840.10040.4.3": 'dsa-with-sha1', + "1.2.840.10040.4.3": "dsaWithSha1", "1.3.6.1.4.1.11129.2.4.2": "certificateExtension", "1.3.6.1.4.1.311.60.2.1.2": "jurisdictionOfIncorporationSP", "1.3.6.1.4.1.311.60.2.1.3": "jurisdictionOfIncorporationC", @@ -264,7 +265,7 @@ class OID { "1.2.840.113549.2.5": "md5", "2.16.840.1.113733.1.7.23.6": "VeriSign EV policy", "2.23.140.1.1": "extendedValidation", - "2.23.140.1.2.2": "extendedValidation", + "2.23.140.1.2.2": "organizationValidated", "2.5.29.14": "subjectKeyIdentifier", "2.5.29.15": "keyUsage", "2.5.29.17": "subjectAltName", diff --git a/lib/src/X509Certificate/x509_certificate.dart b/lib/src/X509Certificate/x509_certificate.dart index f8e02a4d..0d70a800 100644 --- a/lib/src/X509Certificate/x509_certificate.dart +++ b/lib/src/X509Certificate/x509_certificate.dart @@ -228,16 +228,16 @@ class X509Certificate { return value; } - /// Gets the signature value (the raw signature bits) from the certificate. + ///Gets the signature value (the raw signature bits) from the certificate. List get signature => asn1[0].subAtIndex(2)?.value as List; - /// Gets the signature algorithm name for the certificate signature algorithm. + ///Gets the signature algorithm name for the certificate signature algorithm. String get sigAlgName => OID.fromValue(sigAlgOID ?? "")?.name(); - /// Gets the signature algorithm OID string from the certificate. + ///Gets the signature algorithm OID string from the certificate. String get sigAlgOID => block1.subAtIndex(2)?.subAtIndex(0)?.value as String; - /// Gets the DER-encoded signature algorithm parameters from this certificate's signature algorithm. + ///Gets the DER-encoded signature algorithm parameters from this certificate's signature algorithm. List get sigAlgParams => null; ///Gets a boolean array representing bits of the KeyUsage extension, (OID = 2.5.29.15). @@ -262,7 +262,7 @@ class X509Certificate { if (sub != null && sub.length > 0) { var data = sub.last.subAtIndex(0)?.value as List; int bits = (data != null && data.length > 0) ? data.first ?? 0 : 0; - for (var index = 0; index < 7; index++) { + for (var index = 0; index < 8; index++) { var value = bits & (1 << index).toUnsigned(8) != 0; result.insert(0, value); } @@ -321,12 +321,53 @@ class X509Certificate { ///Gets the certificate constraints path length from the ///critical BasicConstraints extension, (OID = 2.5.29.19). - int get basicConstraints => extensionObject(oid: OID.basicConstraints)?.value as int ?? -1; + int get basicConstraints { + var sub = extensionObject(oid: OID.basicConstraints)?.block?.lastSub()?.lastSub()?.lastSub(); + if (sub != null) { + if (sub.value is List) { + return (sub.value as List).length; + } + } + return -1; + } + + ///Gets the raw bits from the Subject Key Identifier (SKID) extension, (OID = 2.5.29.14). + List get subjectKeyIdentifier => + extensionObject(oid: OID.subjectKeyIdentifier)?.block?.lastSub()?.lastSub()?.value ?? []; + + ///Gets the raw bits from the Authority Key Identifier extension, (OID = 2.5.29.35). + List get authorityKeyIdentifier => + extensionObject(oid: OID.authorityKeyIdentifier)?.block?.lastSub()?.lastSub()?.firstSub()?.value ?? []; + + ///Gets the list of certificate policies from the CertificatePolicies extension, (OID = 2.5.29.32). + List get certificatePolicies => + extensionObject(oid: OID.certificatePolicies)?.block?.lastSub()?.firstSub()?.sub?.map((e) => e.firstSub()?.value as String)?.toList() ?? []; + + ///Gets the list of CRL distribution points from the CRLDistributionPoints extension, (OID = 2.5.29.31). + List get cRLDistributionPoints => + extensionObject(oid: OID.cRLDistributionPoints)?.block?.lastSub()?.firstSub()?.sub?.map((e) => e.firstSub()?.firstSub()?.firstSub()?.value as String)?.toList() ?? []; + + ///Gets the map of the format (as a key) and location (as a value) of additional information + ///about the CA who issued the certificate in which this extension appears + ///from the AuthorityInfoAccess extension, (OID = 1.3.6.1.5.5.5.7.1.1). + Map get authorityInfoAccess { + var result = {}; + var sub = extensionObject(oid: OID.authorityInfoAccess)?.block?.lastSub()?.firstSub()?.sub; + if (sub != null) { + sub.forEach((element) { + if (element.subCount() > 1) { + result.putIfAbsent(element.subAtIndex(0).value, + () => element.subAtIndex(1).value); + } + }); + } + return result; + } List get extensionBlocks => block1.atIndex(X509BlockPosition.extensions)?.subAtIndex(0)?.sub; - ///Gets the extension information of the given OID code or enum. + ///Gets the extension information of the given OID code or enum string value. X509Extension extensionObject({String oidValue, OID oid}) { if (oidValue == null && oid != null) { oidValue = oid.toValue(); @@ -346,21 +387,7 @@ class X509Certificate { ///Format subject/issuer information in RFC1779 String blockDistinguishedName({@required ASN1Object block}) { var result = ""; - List oidNames = [ - ASN1DistinguishedNames.COMMON_NAME, - ASN1DistinguishedNames.DN_QUALIFIER, - ASN1DistinguishedNames.SERIAL_NUMBER, - ASN1DistinguishedNames.GIVEN_NAME, - ASN1DistinguishedNames.SURNAME, - ASN1DistinguishedNames.ORGANIZATIONAL_UNIT_NAME, - ASN1DistinguishedNames.ORGANIZATION_NAME, - ASN1DistinguishedNames.STREET_ADDRESS, - ASN1DistinguishedNames.LOCALITY_NAME, - ASN1DistinguishedNames.STATE_OR_PROVINCE_NAME, - ASN1DistinguishedNames.COUNTRY_NAME, - ASN1DistinguishedNames.EMAIL - ]; - for (var oidName in oidNames) { + for (var oidName in ASN1DistinguishedNames.values) { var oidBlock = block.findOid(oidValue: oidName.oid()); if (oidBlock != null) { if (result.isNotEmpty) { @@ -419,6 +446,11 @@ class X509Certificate { "nonCriticalExtensionOIDs": nonCriticalExtensionOIDs, "encoded": encoded, "publicKey": publicKey?.toMap(), + "subjectKeyIdentifier": subjectKeyIdentifier, + "authorityKeyIdentifier": authorityKeyIdentifier, + "certificatePolicies": certificatePolicies, + "cRLDistributionPoints": cRLDistributionPoints, + "authorityInfoAccess": authorityInfoAccess, }; } diff --git a/lib/src/X509Certificate/x509_extension.dart b/lib/src/X509Certificate/x509_extension.dart index f1934429..44c42105 100644 --- a/lib/src/X509Certificate/x509_extension.dart +++ b/lib/src/X509Certificate/x509_extension.dart @@ -39,9 +39,9 @@ class X509Extension { List get valueAsStrings { var result = []; - var sub = []; + var sub; try { - sub = block.sub?.last?.sub?.last?.sub; + sub = block.sub?.last?.sub?.last?.sub ?? []; } catch (e) {} for (var item in sub) {