Compare commits
1 Commits
security-h
...
check-uac-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e1ab51398 |
@@ -4,6 +4,7 @@ import 'dart:convert';
|
||||
import 'package:arbiter/features/connection/connection.dart';
|
||||
import 'package:arbiter/features/connection/server_info_storage.dart';
|
||||
import 'package:arbiter/features/identity/pk_manager.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:arbiter/proto/arbiter.pbgrpc.dart';
|
||||
import 'package:arbiter/proto/user_agent/auth.pb.dart' as ua_auth;
|
||||
import 'package:arbiter/proto/user_agent.pb.dart';
|
||||
@@ -45,6 +46,18 @@ class ConnectionException implements Exception {
|
||||
String toString() => message;
|
||||
}
|
||||
|
||||
String certificateFingerprintHex(List<int> derBytes) {
|
||||
return sha256.convert(derBytes).toString();
|
||||
}
|
||||
|
||||
bool isPinnedServerCertificate({
|
||||
required String expectedFingerprint,
|
||||
required List<int> certificateDer,
|
||||
}) {
|
||||
return certificateFingerprintHex(certificateDer) ==
|
||||
expectedFingerprint.toLowerCase();
|
||||
}
|
||||
|
||||
Future<Connection> connectAndAuthorize(
|
||||
StoredServerInfo serverInfo,
|
||||
KeyHandle key, {
|
||||
@@ -155,7 +168,12 @@ Future<Connection> _connect(StoredServerInfo serverInfo) async {
|
||||
connectTimeout: const Duration(seconds: 10),
|
||||
credentials: ChannelCredentials.secure(
|
||||
onBadCertificate: (cert, host) {
|
||||
return true;
|
||||
final isExpectedHost = host == serverInfo.address;
|
||||
final isPinnedCert = isPinnedServerCertificate(
|
||||
expectedFingerprint: serverInfo.caCertFingerprint,
|
||||
certificateDer: cert.der,
|
||||
);
|
||||
return isExpectedHost && isPinnedCert;
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import 'package:arbiter/features/connection/auth.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('certificate pinning helpers', () {
|
||||
test('certificateFingerprintHex returns SHA-256 in hex', () {
|
||||
final fingerprint = certificateFingerprintHex('abc'.codeUnits);
|
||||
|
||||
expect(
|
||||
fingerprint,
|
||||
'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad',
|
||||
);
|
||||
});
|
||||
|
||||
test('isPinnedServerCertificate matches expected fingerprint', () {
|
||||
final matches = isPinnedServerCertificate(
|
||||
expectedFingerprint:
|
||||
'BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD',
|
||||
certificateDer: 'abc'.codeUnits,
|
||||
);
|
||||
|
||||
expect(matches, isTrue);
|
||||
});
|
||||
|
||||
test('isPinnedServerCertificate rejects mismatched fingerprint', () {
|
||||
final matches = isPinnedServerCertificate(
|
||||
expectedFingerprint:
|
||||
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
||||
certificateDer: 'abc'.codeUnits,
|
||||
);
|
||||
|
||||
expect(matches, isFalse);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user