Compare commits
2 Commits
check-uac-
...
28f84d03ab
| Author | SHA1 | Date | |
|---|---|---|---|
| 28f84d03ab | |||
|
|
e88df432fb |
@@ -4,7 +4,7 @@
|
|||||||
"cargo:cargo-vet" = "0.10.2"
|
"cargo:cargo-vet" = "0.10.2"
|
||||||
flutter = "3.38.9-stable"
|
flutter = "3.38.9-stable"
|
||||||
protoc = "29.6"
|
protoc = "29.6"
|
||||||
"rust" = {version = "1.93.0", components = "clippy"}
|
"rust" = {version = "1.93.0", components = "clippy,rust-analyzer"}
|
||||||
"cargo:cargo-features-manager" = "0.11.1"
|
"cargo:cargo-features-manager" = "0.11.1"
|
||||||
"cargo:cargo-nextest" = "0.9.126"
|
"cargo:cargo-nextest" = "0.9.126"
|
||||||
"cargo:cargo-shear" = "latest"
|
"cargo:cargo-shear" = "latest"
|
||||||
|
|||||||
780
server/Cargo.lock
generated
780
server/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -16,22 +16,22 @@ tonic = { version = "0.14.5", features = [
|
|||||||
"zstd",
|
"zstd",
|
||||||
] }
|
] }
|
||||||
tracing = "0.1.44"
|
tracing = "0.1.44"
|
||||||
tokio = { version = "1.50.0", features = ["full"] }
|
tokio = { version = "1.51.1", features = ["full"] }
|
||||||
ed25519-dalek = { version = "3.0.0-pre.6", features = ["rand_core"] }
|
ed25519-dalek = { version = "3.0.0-pre.6", features = ["rand_core"] }
|
||||||
chrono = { version = "0.4.44", features = ["serde"] }
|
chrono = { version = "0.4.44", features = ["serde"] }
|
||||||
rand = "0.10.0"
|
rand = "0.10.1"
|
||||||
rustls = { version = "0.23.37", features = ["aws-lc-rs", "logging", "prefer-post-quantum", "std"], default-features = false }
|
rustls = { version = "0.23.38", features = ["aws-lc-rs", "logging", "prefer-post-quantum", "std"], default-features = false }
|
||||||
smlang = "0.8.0"
|
smlang = "0.8.0"
|
||||||
thiserror = "2.0.18"
|
thiserror = "2.0.18"
|
||||||
async-trait = "0.1.89"
|
async-trait = "0.1.89"
|
||||||
futures = "0.3.32"
|
futures = "0.3.32"
|
||||||
tokio-stream = { version = "0.1.18", features = ["full"] }
|
tokio-stream = { version = "0.1.18", features = ["full"] }
|
||||||
kameo = "0.19.2"
|
kameo = "0.20.0"
|
||||||
prost-types = { version = "0.14.3", features = ["chrono"] }
|
prost-types = { version = "0.14.3", features = ["chrono"] }
|
||||||
x25519-dalek = { version = "2.0.1", features = ["getrandom"] }
|
x25519-dalek = { version = "2.0.1", features = ["getrandom"] }
|
||||||
rstest = "0.26.1"
|
rstest = "0.26.1"
|
||||||
rustls-pki-types = "1.14.0"
|
rustls-pki-types = "1.14.0"
|
||||||
alloy = "1.7.3"
|
alloy = "2.0.0"
|
||||||
rcgen = { version = "0.14.7", features = [
|
rcgen = { version = "0.14.7", features = [
|
||||||
"aws_lc_rs",
|
"aws_lc_rs",
|
||||||
"pem",
|
"pem",
|
||||||
@@ -40,11 +40,11 @@ rcgen = { version = "0.14.7", features = [
|
|||||||
], default-features = false }
|
], default-features = false }
|
||||||
k256 = { version = "0.13.4", features = ["ecdsa", "pkcs8"] }
|
k256 = { version = "0.13.4", features = ["ecdsa", "pkcs8"] }
|
||||||
rsa = { version = "0.9", features = ["sha2"] }
|
rsa = { version = "0.9", features = ["sha2"] }
|
||||||
sha2 = "0.10"
|
sha2 = "0.11"
|
||||||
spki = "0.7"
|
spki = "0.8"
|
||||||
prost = "0.14.3"
|
prost = "0.14.3"
|
||||||
miette = { version = "7.6.0", features = ["fancy", "serde"] }
|
miette = { version = "7.6.0", features = ["fancy", "serde"] }
|
||||||
mutants = "0.0.4"
|
mutants = "0.0.4"
|
||||||
ml-dsa = { version = "0.1.0-rc.8", features = ["zeroize"] }
|
ml-dsa = { version = "0.1.0-rc.8", features = ["zeroize"] }
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
hmac = "0.12.1"
|
hmac = "0.13.0"
|
||||||
|
|||||||
@@ -21,6 +21,6 @@ tokio.workspace = true
|
|||||||
tokio-stream.workspace = true
|
tokio-stream.workspace = true
|
||||||
thiserror.workspace = true
|
thiserror.workspace = true
|
||||||
http = "1.4.0"
|
http = "1.4.0"
|
||||||
rustls-webpki = { version = "0.103.10", features = ["aws-lc-rs"] }
|
rustls-webpki = { version = "0.103.12", features = ["aws-lc-rs"] }
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
rand.workspace = true
|
rand.workspace = true
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ x25519-dalek.workspace = true
|
|||||||
k256.workspace = true
|
k256.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
insta = "1.46.3"
|
insta = "1.47.2"
|
||||||
proptest = "1.11.0"
|
proptest = "1.11.0"
|
||||||
rstest.workspace = true
|
rstest.workspace = true
|
||||||
test-log = { version = "0.2", default-features = false, features = ["trace"] }
|
test-log = { version = "0.2", default-features = false, features = ["trace"] }
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use diesel::{
|
|||||||
dsl::{insert_into, update},
|
dsl::{insert_into, update},
|
||||||
};
|
};
|
||||||
use diesel_async::{AsyncConnection, RunQueryDsl};
|
use diesel_async::{AsyncConnection, RunQueryDsl};
|
||||||
use hmac::Mac as _;
|
use hmac::{KeyInit as _, Mac as _};
|
||||||
use kameo::{Actor, Reply, messages};
|
use kameo::{Actor, Reply, messages};
|
||||||
use strum::{EnumDiscriminants, IntoDiscriminant};
|
use strum::{EnumDiscriminants, IntoDiscriminant};
|
||||||
use tracing::{error, info};
|
use tracing::{error, info};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import 'dart:convert';
|
|||||||
import 'package:arbiter/features/connection/connection.dart';
|
import 'package:arbiter/features/connection/connection.dart';
|
||||||
import 'package:arbiter/features/connection/server_info_storage.dart';
|
import 'package:arbiter/features/connection/server_info_storage.dart';
|
||||||
import 'package:arbiter/features/identity/pk_manager.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/arbiter.pbgrpc.dart';
|
||||||
import 'package:arbiter/proto/user_agent/auth.pb.dart' as ua_auth;
|
import 'package:arbiter/proto/user_agent/auth.pb.dart' as ua_auth;
|
||||||
import 'package:arbiter/proto/user_agent.pb.dart';
|
import 'package:arbiter/proto/user_agent.pb.dart';
|
||||||
@@ -46,18 +45,6 @@ class ConnectionException implements Exception {
|
|||||||
String toString() => message;
|
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(
|
Future<Connection> connectAndAuthorize(
|
||||||
StoredServerInfo serverInfo,
|
StoredServerInfo serverInfo,
|
||||||
KeyHandle key, {
|
KeyHandle key, {
|
||||||
@@ -168,12 +155,7 @@ Future<Connection> _connect(StoredServerInfo serverInfo) async {
|
|||||||
connectTimeout: const Duration(seconds: 10),
|
connectTimeout: const Duration(seconds: 10),
|
||||||
credentials: ChannelCredentials.secure(
|
credentials: ChannelCredentials.secure(
|
||||||
onBadCertificate: (cert, host) {
|
onBadCertificate: (cert, host) {
|
||||||
final isExpectedHost = host == serverInfo.address;
|
return true;
|
||||||
final isPinnedCert = isPinnedServerCertificate(
|
|
||||||
expectedFingerprint: serverInfo.caCertFingerprint,
|
|
||||||
certificateDer: cert.der,
|
|
||||||
);
|
|
||||||
return isExpectedHost && isPinnedCert;
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
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