about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--LibMatrix.Federation/AuthenticatedFederationClient.cs9
-rw-r--r--LibMatrix.Federation/Extensions/Ed25519Extensions.cs1
-rw-r--r--LibMatrix.Federation/Extensions/XMatrixAuthorizationSchemeExtensions.cs11
-rw-r--r--LibMatrix.Federation/XMatrixAuthorizationScheme.cs10
-rw-r--r--LibMatrix/Responses/Federation/ServerKeysResponse.cs4
-rw-r--r--Utilities/LibMatrix.FederationTest/Controllers/RemoteServerPingController.cs4
-rw-r--r--Utilities/LibMatrix.FederationTest/Controllers/Spec/FederationKeysController.cs9
-rw-r--r--Utilities/LibMatrix.FederationTest/Controllers/TestController.cs47
-rw-r--r--Utilities/LibMatrix.FederationTest/Services/FederationKeyStore.cs31
9 files changed, 77 insertions, 49 deletions
diff --git a/LibMatrix.Federation/AuthenticatedFederationClient.cs b/LibMatrix.Federation/AuthenticatedFederationClient.cs

index ee4bb25..95af72f 100644 --- a/LibMatrix.Federation/AuthenticatedFederationClient.cs +++ b/LibMatrix.Federation/AuthenticatedFederationClient.cs
@@ -4,13 +4,13 @@ using LibMatrix.Homeservers; namespace LibMatrix.Federation; -public class AuthenticatedFederationClient(string federationEndpoint, AuthenticatedFederationClient.AuthenticatedFederationConfiguration config, string? proxy = null) : FederationClient(federationEndpoint, proxy) { - +public class AuthenticatedFederationClient(string federationEndpoint, AuthenticatedFederationClient.AuthenticatedFederationConfiguration config, string? proxy = null) + : FederationClient(federationEndpoint, proxy) { public class AuthenticatedFederationConfiguration { - public required VersionedHomeserverPrivateKey PrivateKey { get; set; } + public required VersionedHomeserverPrivateKey PrivateKey { get; set; } public required string OriginServerName { get; set; } } - + // public async Task<UserDeviceListResponse> GetUserDevicesAsync(string userId) { // var response = await HttpClient.SendAsync(new XMatrixAuthorizationScheme.XMatrixRequestSignature() { // OriginServerName = config.OriginServerName, @@ -20,5 +20,4 @@ public class AuthenticatedFederationClient(string federationEndpoint, Authentica // }.ToSignedHttpRequestMessage(config.PrivateKey)); // return response; // } - } \ No newline at end of file diff --git a/LibMatrix.Federation/Extensions/Ed25519Extensions.cs b/LibMatrix.Federation/Extensions/Ed25519Extensions.cs
index e5a9e5d..ada6a3d 100644 --- a/LibMatrix.Federation/Extensions/Ed25519Extensions.cs +++ b/LibMatrix.Federation/Extensions/Ed25519Extensions.cs
@@ -6,5 +6,6 @@ namespace LibMatrix.Federation.Extensions; public static class Ed25519Extensions { public static string ToUnpaddedBase64(this Ed25519PublicKeyParameters key) => UnpaddedBase64.Encode(key.GetEncoded()); + public static string ToUnpaddedBase64(this Ed25519PrivateKeyParameters key) => UnpaddedBase64.Encode(key.GetEncoded()); public static Ed25519PrivateKeyParameters GetPrivateEd25519Key(this VersionedHomeserverPrivateKey key) => new(UnpaddedBase64.Decode(key.PrivateKey), 0); } \ No newline at end of file diff --git a/LibMatrix.Federation/Extensions/XMatrixAuthorizationSchemeExtensions.cs b/LibMatrix.Federation/Extensions/XMatrixAuthorizationSchemeExtensions.cs
index 792264a..b520b1c 100644 --- a/LibMatrix.Federation/Extensions/XMatrixAuthorizationSchemeExtensions.cs +++ b/LibMatrix.Federation/Extensions/XMatrixAuthorizationSchemeExtensions.cs
@@ -4,13 +4,22 @@ using LibMatrix.Abstractions; namespace LibMatrix.Federation.Extensions; public static class XMatrixAuthorizationSchemeExtensions { - public static HttpRequestMessage ToSignedHttpRequestMessage(this XMatrixAuthorizationScheme.XMatrixRequestSignature requestSignature, VersionedHomeserverPrivateKey privateKey) { + public static HttpRequestMessage ToSignedHttpRequestMessage(this XMatrixAuthorizationScheme.XMatrixRequestSignature requestSignature, + VersionedHomeserverPrivateKey privateKey) { var signature = requestSignature.Sign(privateKey); var requestMessage = new HttpRequestMessage { Method = new HttpMethod(requestSignature.Method), RequestUri = new Uri(requestSignature.Uri, UriKind.Relative) }; + var headerValue = new XMatrixAuthorizationScheme.XMatrixAuthorizationHeader() { + Origin = requestSignature.OriginServerName, + Key = privateKey.KeyId, + Destination = requestSignature.DestinationServerName, + Signature = signature.Signatures[requestSignature.OriginServerName][privateKey.KeyId] + }.ToHeaderValue(); + requestMessage.Headers.Add("Authorization", headerValue); + if (requestSignature.Content != null) { requestMessage.Content = JsonContent.Create(requestSignature.Content); } diff --git a/LibMatrix.Federation/XMatrixAuthorizationScheme.cs b/LibMatrix.Federation/XMatrixAuthorizationScheme.cs
index 45899b8..392cd93 100644 --- a/LibMatrix.Federation/XMatrixAuthorizationScheme.cs +++ b/LibMatrix.Federation/XMatrixAuthorizationScheme.cs
@@ -2,6 +2,8 @@ using System.Net.Http.Headers; using System.Text.Json.Nodes; using System.Text.Json.Serialization; using ArcaneLibs.Extensions; +using LibMatrix.Abstractions; +using LibMatrix.Responses.Federation; using Microsoft.Extensions.Primitives; namespace LibMatrix.Federation; @@ -48,6 +50,14 @@ public class XMatrixAuthorizationScheme { }; } + public static XMatrixAuthorizationHeader FromSignedObject(SignedObject<XMatrixRequestSignature> signedObj, VersionedHomeserverPrivateKey currentKey) => + new() { + Origin = signedObj.TypedContent.OriginServerName, + Destination = signedObj.TypedContent.DestinationServerName, + Signature = signedObj.Signatures[signedObj.TypedContent.OriginServerName][currentKey.KeyId], + Key = currentKey.KeyId + }; + public string ToHeaderValue() => $"{Scheme} origin=\"{Origin}\", destination=\"{Destination}\", key=\"{Key}\", sig=\"{Signature}\""; } diff --git a/LibMatrix/Responses/Federation/ServerKeysResponse.cs b/LibMatrix/Responses/Federation/ServerKeysResponse.cs
index cb62e34..982907c 100644 --- a/LibMatrix/Responses/Federation/ServerKeysResponse.cs +++ b/LibMatrix/Responses/Federation/ServerKeysResponse.cs
@@ -38,7 +38,7 @@ public class ServerKeysResponse { [DebuggerDisplay("{Key}")] public class CurrentVerifyKey { [JsonPropertyName("key")] - public string Key { get; set; } + public required string Key { get; set; } } [DebuggerDisplay("{Key} (expired {Expired})")] @@ -52,4 +52,4 @@ public class ServerKeysResponse { set => ExpiredTs = (ulong)new DateTimeOffset(value).ToUnixTimeMilliseconds(); } } -} +} \ No newline at end of file diff --git a/Utilities/LibMatrix.FederationTest/Controllers/RemoteServerPingController.cs b/Utilities/LibMatrix.FederationTest/Controllers/RemoteServerPingController.cs
index 8d3a5ea..ce0e119 100644 --- a/Utilities/LibMatrix.FederationTest/Controllers/RemoteServerPingController.cs +++ b/Utilities/LibMatrix.FederationTest/Controllers/RemoteServerPingController.cs
@@ -20,8 +20,8 @@ public class RemoteServerPingController(FederationTestConfiguration config, Fede try { var ownKey = keyStore.GetCurrentSigningKey(); var hs = new AuthenticatedFederationClient(hsResolveResult.Server, new() { - PrivateKey = , - OriginServerName = null + PrivateKey = ownKey.CurrentSigningKey, + OriginServerName = config.ServerName }); var keys = await hs.GetServerKeysAsync(); responseMessage["version"] = await hs.GetServerVersionAsync(); diff --git a/Utilities/LibMatrix.FederationTest/Controllers/Spec/FederationKeysController.cs b/Utilities/LibMatrix.FederationTest/Controllers/Spec/FederationKeysController.cs
index 6516415..d96bef5 100644 --- a/Utilities/LibMatrix.FederationTest/Controllers/Spec/FederationKeysController.cs +++ b/Utilities/LibMatrix.FederationTest/Controllers/Spec/FederationKeysController.cs
@@ -23,18 +23,19 @@ public class FederationKeysController(FederationTestConfiguration config, Federa if (_cachedServerKeysResponse == null || _cachedServerKeysResponse.TypedContent.ValidUntil < DateTime.Now + TimeSpan.FromSeconds(30)) { var keys = keyStore.GetCurrentSigningKey(); _cachedServerKeysResponse = new ServerKeysResponse() { - ValidUntil = DateTime.Now + TimeSpan.FromMinutes(1), + ValidUntil = DateTime.Now + TimeSpan.FromMinutes(5), ServerName = config.ServerName, OldVerifyKeys = [], VerifyKeysById = new() { { - new() { Algorithm = "ed25519", KeyId = "0" }, new ServerKeysResponse.CurrentVerifyKey() { - Key = keys.publicKey.ToUnpaddedBase64(), + keys.CurrentSigningKey.KeyId, new ServerKeysResponse.CurrentVerifyKey() { + Key = keys.CurrentSigningKey.PublicKey //.ToUnpaddedBase64(), } } } - }.Sign(config.ServerName, new VersionedKeyId() { Algorithm = "ed25519", KeyId = "0" }, keys.privateKey); + }.Sign(keys.CurrentSigningKey); } + _serverKeyCacheLock.Release(); return _cachedServerKeysResponse; diff --git a/Utilities/LibMatrix.FederationTest/Controllers/TestController.cs b/Utilities/LibMatrix.FederationTest/Controllers/TestController.cs
index 9c0981d..900c8a0 100644 --- a/Utilities/LibMatrix.FederationTest/Controllers/TestController.cs +++ b/Utilities/LibMatrix.FederationTest/Controllers/TestController.cs
@@ -1,10 +1,8 @@ using System.Text.Json.Nodes; -using LibMatrix.Abstractions; using LibMatrix.Extensions; using LibMatrix.Federation; using LibMatrix.Federation.Extensions; using LibMatrix.FederationTest.Services; -using LibMatrix.Homeservers; using Microsoft.AspNetCore.Mvc; namespace LibMatrix.FederationTest.Controllers; @@ -21,32 +19,33 @@ public class TestController(FederationTestConfiguration config, FederationKeySto BaseAddress = new Uri("https://matrix.rory.gay") }; - var keyId = new VersionedKeyId() { - Algorithm = "ed25519", - KeyId = "0" - }; + var currentKey = keyStore.GetCurrentSigningKey().CurrentSigningKey; var signatureData = new XMatrixAuthorizationScheme.XMatrixRequestSignature() { - Method = "GET", - Uri = "/_matrix/federation/v1/user/devices/@emma:rory.gay", - OriginServerName = config.ServerName, - DestinationServerName = "rory.gay" - } - .Sign(config.ServerName, keyId, keyStore.GetCurrentSigningKey().privateKey); - - var signature = signatureData.Signatures[config.ServerName][keyId]; - var headerValue = new XMatrixAuthorizationScheme.XMatrixAuthorizationHeader() { - Origin = config.ServerName, - Destination = "rory.gay", - Key = keyId, - Signature = signature - }.ToHeaderValue(); - - var req = new HttpRequestMessage(HttpMethod.Get, "/_matrix/federation/v1/user/devices/@emma:rory.gay"); - req.Headers.Add("Authorization", headerValue); - + OriginServerName = config.ServerName, + Method = "GET", + DestinationServerName = "rory.gay", + Uri = "/_matrix/federation/v1/user/devices/@emma:rory.gay", + }; + // .Sign(currentKey); + // + // var signature = signatureData.Signatures[config.ServerName][currentKey.KeyId]; + // var headerValue = new XMatrixAuthorizationScheme.XMatrixAuthorizationHeader() { + // Origin = config.ServerName, + // Key = currentKey.KeyId, + // Destination = "rory.gay", + // Signature = signature + // }.ToHeaderValue(); + + // var req = new HttpRequestMessage(HttpMethod.Get, "/_matrix/federation/v1/user/devices/@emma:rory.gay"); + // req.Headers.Add("Authorization", headerValue); + + var req = signatureData.ToSignedHttpRequestMessage(currentKey); var response = await hc.SendAsync(req); var content = await response.Content.ReadFromJsonAsync<JsonObject>(); return content!; } + + // [HttpGet("/testMakeJoin")] + // public async Task<JsonObject> GetTestMakeJoin() { } } \ No newline at end of file diff --git a/Utilities/LibMatrix.FederationTest/Services/FederationKeyStore.cs b/Utilities/LibMatrix.FederationTest/Services/FederationKeyStore.cs
index e916703..b892dbb 100644 --- a/Utilities/LibMatrix.FederationTest/Services/FederationKeyStore.cs +++ b/Utilities/LibMatrix.FederationTest/Services/FederationKeyStore.cs
@@ -1,5 +1,7 @@ using System.Text.Json; +using ArcaneLibs.Extensions; using LibMatrix.Abstractions; +using LibMatrix.Federation.Extensions; using LibMatrix.FederationTest.Utilities; using Org.BouncyCastle.Crypto.Parameters; @@ -11,34 +13,41 @@ public class FederationKeyStore(FederationTestConfiguration config) { } private static (Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey) currentKeyPair = default; - + public class PrivateKeyCollection { - public required VersionedHomeserverPrivateKey CurrentSigningKey { get; set; } } - + public PrivateKeyCollection GetCurrentSigningKey() { - if(!Directory.Exists(config.KeyStorePath)) Directory.CreateDirectory(config.KeyStorePath); + if (!Directory.Exists(config.KeyStorePath)) Directory.CreateDirectory(config.KeyStorePath); var privateKeyPath = Path.Combine(config.KeyStorePath, "private-keys.json"); if (!File.Exists(privateKeyPath)) { var keyPair = InternalGetSigningKey(); - var privateKey = new VersionedHomeserverPrivateKey { - PrivateKey = keyPair.privateKey.GetEncoded().ToUnpaddedBase64(), + var privateKey = new PrivateKeyCollection() { + CurrentSigningKey = new VersionedHomeserverPrivateKey { + ServerName = config.ServerName, + KeyId = new() { + Algorithm = "ed25519", + KeyId = "0" + }, + PrivateKey = keyPair.privateKey.ToUnpaddedBase64(), + PublicKey = keyPair.publicKey.ToUnpaddedBase64(), + } }; File.WriteAllText(privateKeyPath, privateKey.ToJson()); } - - return JsonSerializer.Deserialize<PrivateKeyCollection>() + + return JsonSerializer.Deserialize<PrivateKeyCollection>(File.ReadAllText(privateKeyPath))!; } private (Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey) InternalGetSigningKey() { if (currentKeyPair != default) { return currentKeyPair; } - - if(!Directory.Exists(config.KeyStorePath)) Directory.CreateDirectory(config.KeyStorePath); - + + if (!Directory.Exists(config.KeyStorePath)) Directory.CreateDirectory(config.KeyStorePath); + var privateKeyPath = Path.Combine(config.KeyStorePath, "signing.key"); if (!File.Exists(privateKeyPath)) { var keyPair = Ed25519Utils.GenerateKeyPair();