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();
|