gpt4 book ai didi

android - 在 2021 年 9 月 30 日之后使用 LetsEncrypt SSL 证书在 Android 7 CERTIFICATE_VERIFY_FAILED 上 flutter

转载 作者:行者123 更新时间:2023-12-04 23:36:15 25 4
gpt4 key购买 nike

2021 年 9 月 30 日之后,在旧的 Android 7 设备上使用 Let's Encrypt SSL 证书对网站的 https 获取/发布请求失败并出现以下错误:

HandshakeException: Handshake error in client (OS Error: CERTIFICATE_VERIFY_FAILED: certificate has expired(handshake.cc:354))
此错误不会出现在较新的 Android 或 Apple 设备上。
为什么这个错误会在旧的 Android 手机上突然出现?
我该如何解决这个问题?

最佳答案

解决方案
在 Flutter 中,为了再次在旧设备上建立 SSL https 连接到 Let's Encrypt SSL 保护的网站,我们可以通过 SecurityContext 提供 Let's Encrypt 的可信证书。至dart:io HttpClient对象(来自 dart 原生通信库),我们可以直接使用它来进行 https get/post 调用,或者我们可以提供自定义的 HttpClient flutter/飞镖package:http IOClient如果我们使用 popular pub.dev package .
例子
这是一个 Flutter 单元测试,它创建了 dart:io HttpClientSecurityContext提供给它的 Let's Encrypt 根证书。那么,这个HttpClient提供给 package:http IOClient哪个工具是 Client接口(interface),可用于所有常用的get , post等电话。

import 'dart:convert';
import 'dart:typed_data';
import 'dart:io';

import 'package:test/test.dart';
import 'package:http/http.dart' as http;
import 'package:http/io_client.dart';

void main() {
const sslUrl = 'https://valid-isrgrootx1.letsencrypt.org/';

/// From dart:io, create a HttpClient with a trusted certificate [cert]
/// added to SecurityContext.
/// Wrapped in try catch in case the certificate is already trusted by
/// device/os, which will cause an exception to be thrown.
HttpClient customHttpClient({String cert}) {
SecurityContext context = SecurityContext.defaultContext;

try {
if (cert != null) {
Uint8List bytes = utf8.encode(cert);
context.setTrustedCertificatesBytes(bytes);
print('createHttpClient() - cert added!');
}
} on TlsException catch (e) {
if (e?.osError?.message != null &&
e.osError.message.contains('CERT_ALREADY_IN_HASH_TABLE')) {
print('createHttpClient() - cert already trusted! Skipping.');
} else {
print('createHttpClient().setTrustedCertificateBytes EXCEPTION: $e');
rethrow;
}
}

return new HttpClient(context: context);
}

/// Use package:http Client with our custom dart:io HttpClient with added
/// LetsEncrypt trusted certificate
http.Client createLEClient() {
IOClient ioClient;
ioClient = IOClient(customHttpClient(cert: ISRG_X1));
return ioClient;
}

/// Example using a custom package:http Client
/// that will work with devices missing LetsEncrypt
/// ISRG Root X1 certificates, like old Android 7 devices.
test('HTTP client to LetsEncrypt SSL website', () async {
http.Client _client = createLEClient();
http.Response _response = await _client.get(sslUrl);
print(_response.body);
expect(_response.statusCode, 200);
_client.close(); // remember to close client as per https://pub.dev/packages/http
});
}

/// This is LetsEncrypt's self-signed trusted root certificate authority
/// certificate, issued under common name: ISRG Root X1 (Internet Security
/// Research Group). Used in handshakes to negotiate a Transport Layer Security
/// connection between endpoints. This certificate is missing from older devices
/// that don't get OS updates such as Android 7 and older. But, we can supply
/// this certificate manually to our HttpClient via SecurityContext so it can be
/// used when connecting to URLs protected by LetsEncrypt SSL certificates.
/// PEM format LE self-signed cert from here: https://letsencrypt.org/certificates/
const String ISRG_X1 = """-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----""";
由于此单元测试是在 的台式机/笔记本电脑上运行的有 ISRG Root X1 证书,它可能不是很有趣/有用。获得更新的系统将安装此证书颁发机构 (CA) 证书,并且“应该”在验证 Let's Encrypt SSL 证书的“信任链”时没有问题。
但是在 旧设备 没有 ISRG Root X1 证书并且永远不会,使用上面的两个函数 customHttpClient()createLEClient()当 LE 的 CA 证书(ISRG Root X1)丢失时,我们可以与 Let's Encrypt SSL 保护的 Internet 资源建立 https/TLS 连接。
为什么会这样
Let's Encrypt SSL 证书是使用数字签名信任 (DST) 的交叉签名创建/颁发的,DST 是一个较旧的、完善的证书颁发机构 (CA)。
被广泛信任的 CA 交叉签名意味着 Let's Ecrypt (LE) SSL 证书从第一天(大约 5 年前)开始就被几乎所有应用程序和设备接受为合法证书。
DST 用于交叉签署 LE 证书的证书于 2021 年 9 月 30 日到期。这意味着 LE 证书的“信任链”不再被一些旧设备接受。
有几种解决方案可以解决这个问题,这只是一种不需要最终用户干预的方法。
为什么这会影响 Android 7.1.1 之前的 Flutter
(这是我的猜测……)
Dart VM(以及因此,Flutter)使用 BoringSSL library ,OpenSSL 的 Google 分支。
当找到任何匹配的信任链、无效(即过期)或其他情况时,Dart VM 中的 BoringSSL 将停止搜索有效的信任链。 Google 的 Dart 团队遇到了这个 issue in June (不是因为 Let's Encrypt 的 DST 交叉签名过期,而是类似的问题)并创建了 patch for it on Aug 26 .该补丁可能会随 Dart 2.15 一起推出。当那个版本的 Dart 被引入 Flutter 时,我希望/猜测这个补丁会解决这个问题。
更多信息
Background on expiration of DST root cert from LE
More background on DST expiration & cert chaining help from LE
Let's Encrypt has an ongoing mega-thread for the issues caused by the DST root cert expiration here

关于android - 在 2021 年 9 月 30 日之后使用 LetsEncrypt SSL 证书在 Android 7 CERTIFICATE_VERIFY_FAILED 上 flutter ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69511057/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com