2 Commits

Author SHA1 Message Date
28f84d03ab Merge pull request 'housekeeping(server): dependencies upgrade' (#89) from push-zmvtzuwrnyyv into main
Some checks failed
ci/woodpecker/push/server-audit Pipeline was successful
ci/woodpecker/push/server-vet Pipeline failed
ci/woodpecker/push/server-lint Pipeline was successful
ci/woodpecker/push/server-test Pipeline was successful
Reviewed-on: #89
2026-04-17 19:20:50 +00:00
Skipper
e88df432fb housekeeping(server): dependencies upgrade
Some checks failed
ci/woodpecker/pr/server-lint Pipeline was successful
ci/woodpecker/pr/server-audit Pipeline was successful
ci/woodpecker/pr/server-vet Pipeline failed
ci/woodpecker/pr/server-test Pipeline failed
2026-04-14 19:10:07 +02:00
8 changed files with 522 additions and 337 deletions

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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"

View File

@@ -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

View File

@@ -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"] }

View File

@@ -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};

View File

@@ -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;
}, },
), ),
), ),

View File

@@ -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);
});
});
}