如何在 flutter/dart 中执行 SSL public 键固定?

How to do SSL public key pinning in flutter/dart?

这里是 Flutter 的新手(以及一般的编程)。只熟悉更基本的东西,但我现在遇到了使用 CertificatePinner 的需要,例如 flutter/dart: https://square.github.io/okhttp/3.x/okhttp/okhttp3/CertificatePinner.html(我在之前 kotlin/java 工作室的 kotlin/java 项目中成功实现了这一点)。 我的目标是固定 public 密钥(不是证书)

我只有 public 字符串形式的键,如下所示,没有别的"sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="

我该如何实现这一目标?我已经在 github 上的一个未决问题中提出这个问题,但还没有得到任何答复 (https://github.com/dart-lang/sdk/issues/35981)。希望有人已经设法实现这一目标。

我还搜索了其他来源。我认为对我来说最接近解决方案的是 但我不太明白那里正在做什么,我不能发表评论在那里提问,因为我还没有足够的声誉。

为了比较,我想做的就是在 flutter/dart 中使用以下几行代码实现我在 java/kotlin 中可以实现的相同目标:

 String hostname = "publicobject.com";
 CertificatePinner certificatePinner = new CertificatePinner.Builder()
     .add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
     .build();

感谢您的帮助

从您引用的答案中的代码开始。获取 DER 格式的证书并开始对其进行解码。

ASN1Parser p = ASN1Parser(der);
ASN1Sequence signedCert = p.nextObject() as ASN1Sequence;
ASN1Sequence cert = signedCert.elements[0] as ASN1Sequence;
ASN1Sequence pubKeyElement = cert.elements[6] as ASN1Sequence;
// this is the Subject Public Key element, which describes the type of key and actual value

例如,如果我们解码pub.dev的证书,我们发现它是一个模数为65537,值为2347的RSA密钥......:

SEQUENCE (2 elem)
  SEQUENCE (2 elem)
    OBJECT IDENTIFIER 1.2.840.113549.1.1.1 rsaEncryption (PKCS #1)
    NULL
  BIT STRING (1 elem)
    SEQUENCE (2 elem)
      INTEGER (2048 bit) 234782553149463204049153749736864715384123240676730175743244004248041…
      INTEGER 65537

根据 RFC,SPKI 指纹是整个元素的 SHA-256 哈希值。

// you need to import dart:convert and package:crypto/crypto.dart
var hash = base64.encode(sha256.convert(pubKeyElement.contentBytes()).bytes);
var spkiFingerprint = 'sha256/$hash'; // should match the value you have

注意事项

badCertificateCallback 不会提供整个证书链,因此您无法遍历整个链。更糟糕的是,它似乎并不总是提供叶子证书!有时它会提供中间证书。