带 PEM 的 Dart gRPC TLS 证书
Dart gRPC TLS certificates with PEMs
我在整理如何调整我的 Dart gRPC 客户端以使用与我的 Go 客户端一起使用的相同 TLS 设置时遇到了一些麻烦。我已经验证我可以与提供正确 CA 证书、客户端证书和客户端密钥的服务器交互。在 Go 中,我正在使用:
pemServerCA, err := ioutil.ReadFile("pems/ca-cert.pem")
if err != nil {
return nil, err
}
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(pemServerCA) {
return nil, fmt.Errorf("failed to add server CA's certificate")
}
// Load client's certificate and private key
clientCert, err := tls.LoadX509KeyPair("pems/client-cert.pem", "pems/client-key.pem")
if err != nil {
return nil, err
}
// Create the credentials and return it
config := &tls.Config{
Certificates: []tls.Certificate{clientCert},
RootCAs: certPool,
}
只是提供它以防它有助于演示什么是有效的。在 Dart 中,我这样做:
ChannelCredentials credentials = ChannelCredentials.secure(
certificates: utf8.encode(grpcCertificate),
onBadCertificate: (certificate, host) {
return host == apiURL + ':' + apiPort.toString();
},
);
grpcCertificate 包含client-key.pem的内容。我怀疑这是不正确的。我对这样的证书不是很熟练,所以我有点不知所措。我应该为证书提供什么值才能与服务器成功握手?
从上面看来,我似乎需要将我的 PEM 解析为 X.509。在 Go 中这非常简单,不知道如何在 Dart 中处理它。
编辑:我取得了一些进步:
List<int> list = grpcCertificate.codeUnits;
Uint8List cert = Uint8List.fromList(list);
ChannelCredentials credentials = ChannelCredentials.secure(
certificates: cert,
authority: 'localhost',
onBadCertificate: (certificate, host) {
return host == apiURL + ':' + apiPort.toString();
},
);
服务器似乎不太讨厌这个并吐出:
flutter: gRPC Error (code: 14, codeName: UNAVAILABLE, message: Error connecting: TlsException: Failure trusting builtin roots (OS Error:
BAD_PKCS12_DATA(pkcs8_x509.c:645), errno = 0), details: null, rawResponse: null)
谢谢。
我最终在 grpc-dart 问题页面上收到了一些正确的答案。解决方案看起来像这样:
class MyChannelCredentials extends ChannelCredentials {
final Uint8List? certificateChain;
final Uint8List? privateKey;
MyChannelCredentials({
Uint8List? trustedRoots,
this.certificateChain,
this.privateKey,
String? authority,
BadCertificateHandler? onBadCertificate,
}) : super.secure(
certificates: trustedRoots,
authority: authority,
onBadCertificate: onBadCertificate);
@override
SecurityContext get securityContext {
final ctx = super.securityContext;
if (certificateChain != null) {
ctx.useCertificateChainBytes(certificateChain);
}
if (privateKey != null) {
ctx.usePrivateKeyBytes(privateKey);
}
return ctx;
}
}
final cred = MyChannelCredentials(
trustedRoots: File('pems/ca-cert.pem').readAsBytesSync(),
certificateChain: File('pems/client-cert.pem').readAsBytesSync(),
privateKey: File('pems/client-key.pem').readAsBytesSync(),
authority: 'localhost',
);
我在整理如何调整我的 Dart gRPC 客户端以使用与我的 Go 客户端一起使用的相同 TLS 设置时遇到了一些麻烦。我已经验证我可以与提供正确 CA 证书、客户端证书和客户端密钥的服务器交互。在 Go 中,我正在使用:
pemServerCA, err := ioutil.ReadFile("pems/ca-cert.pem")
if err != nil {
return nil, err
}
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(pemServerCA) {
return nil, fmt.Errorf("failed to add server CA's certificate")
}
// Load client's certificate and private key
clientCert, err := tls.LoadX509KeyPair("pems/client-cert.pem", "pems/client-key.pem")
if err != nil {
return nil, err
}
// Create the credentials and return it
config := &tls.Config{
Certificates: []tls.Certificate{clientCert},
RootCAs: certPool,
}
只是提供它以防它有助于演示什么是有效的。在 Dart 中,我这样做:
ChannelCredentials credentials = ChannelCredentials.secure(
certificates: utf8.encode(grpcCertificate),
onBadCertificate: (certificate, host) {
return host == apiURL + ':' + apiPort.toString();
},
);
grpcCertificate 包含client-key.pem的内容。我怀疑这是不正确的。我对这样的证书不是很熟练,所以我有点不知所措。我应该为证书提供什么值才能与服务器成功握手?
从上面看来,我似乎需要将我的 PEM 解析为 X.509。在 Go 中这非常简单,不知道如何在 Dart 中处理它。
编辑:我取得了一些进步:
List<int> list = grpcCertificate.codeUnits;
Uint8List cert = Uint8List.fromList(list);
ChannelCredentials credentials = ChannelCredentials.secure(
certificates: cert,
authority: 'localhost',
onBadCertificate: (certificate, host) {
return host == apiURL + ':' + apiPort.toString();
},
);
服务器似乎不太讨厌这个并吐出:
flutter: gRPC Error (code: 14, codeName: UNAVAILABLE, message: Error connecting: TlsException: Failure trusting builtin roots (OS Error:
BAD_PKCS12_DATA(pkcs8_x509.c:645), errno = 0), details: null, rawResponse: null)
谢谢。
我最终在 grpc-dart 问题页面上收到了一些正确的答案。解决方案看起来像这样:
class MyChannelCredentials extends ChannelCredentials {
final Uint8List? certificateChain;
final Uint8List? privateKey;
MyChannelCredentials({
Uint8List? trustedRoots,
this.certificateChain,
this.privateKey,
String? authority,
BadCertificateHandler? onBadCertificate,
}) : super.secure(
certificates: trustedRoots,
authority: authority,
onBadCertificate: onBadCertificate);
@override
SecurityContext get securityContext {
final ctx = super.securityContext;
if (certificateChain != null) {
ctx.useCertificateChainBytes(certificateChain);
}
if (privateKey != null) {
ctx.usePrivateKeyBytes(privateKey);
}
return ctx;
}
}
final cred = MyChannelCredentials(
trustedRoots: File('pems/ca-cert.pem').readAsBytesSync(),
certificateChain: File('pems/client-cert.pem').readAsBytesSync(),
privateKey: File('pems/client-key.pem').readAsBytesSync(),
authority: 'localhost',
);