[backend/federation] Refactor ActivityStreams & w3id references to use the Constants properties (ISH-57)

This commit is contained in:
Laura Hausmann 2024-02-14 18:13:01 +01:00
parent ff27d7ff16
commit b5a63fd301
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
15 changed files with 72 additions and 62 deletions

View file

@ -2,6 +2,7 @@ namespace Iceshrimp.Backend.Core.Configuration;
public static class Constants { public static class Constants {
public const string ActivityStreamsNs = "https://www.w3.org/ns/activitystreams"; public const string ActivityStreamsNs = "https://www.w3.org/ns/activitystreams";
public const string W3IdSecurityNs = "https://w3id.org/security";
public static readonly string[] SystemUsers = ["instance.actor", "relay.actor"]; public static readonly string[] SystemUsers = ["instance.actor", "relay.actor"];
public static readonly string[] BrowserSafeMimeTypes = [ public static readonly string[] BrowserSafeMimeTypes = [

View file

@ -5,11 +5,11 @@ using JC = Newtonsoft.Json.JsonConverterAttribute;
namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types;
public class ASActivity : ASObject { public class ASActivity : ASObject {
[J("https://www.w3.org/ns/activitystreams#actor")] [J($"{Constants.ActivityStreamsNs}#actor")]
[JC(typeof(ASActorConverter))] [JC(typeof(ASActorConverter))]
public ASActor? Actor { get; set; } public ASActor? Actor { get; set; }
[J("https://www.w3.org/ns/activitystreams#object")] [J($"{Constants.ActivityStreamsNs}#object")]
[JC(typeof(ASObjectConverter))] [JC(typeof(ASObjectConverter))]
public ASObject? Object { get; set; } public ASObject? Object { get; set; }

View file

@ -20,15 +20,15 @@ public class ASActor : ASObject {
[JC(typeof(VC))] [JC(typeof(VC))]
public string? MkSummary { get; set; } public string? MkSummary { get; set; }
[J("https://www.w3.org/ns/activitystreams#summary")] [J($"{Constants.ActivityStreamsNs}#summary")]
[JC(typeof(VC))] [JC(typeof(VC))]
public string? Summary { get; set; } public string? Summary { get; set; }
[J("https://www.w3.org/ns/activitystreams#name")] [J($"{Constants.ActivityStreamsNs}#name")]
[JC(typeof(VC))] [JC(typeof(VC))]
public string? DisplayName { get; set; } public string? DisplayName { get; set; }
[J("https://www.w3.org/ns/activitystreams#preferredUsername")] [J($"{Constants.ActivityStreamsNs}#preferredUsername")]
[JC(typeof(VC))] [JC(typeof(VC))]
public string? Username { get; set; } public string? Username { get; set; }
@ -44,7 +44,7 @@ public class ASActor : ASObject {
[JC(typeof(VC))] [JC(typeof(VC))]
public bool? IsMemorial { get; set; } public bool? IsMemorial { get; set; }
[J("https://www.w3.org/ns/activitystreams#manuallyApprovesFollowers")] [J($"{Constants.ActivityStreamsNs}#manuallyApprovesFollowers")]
[JC(typeof(VC))] [JC(typeof(VC))]
public bool? IsLocked { get; set; } public bool? IsLocked { get; set; }
@ -60,11 +60,11 @@ public class ASActor : ASObject {
[JC(typeof(VC))] [JC(typeof(VC))]
public string? Birthday { get; set; } public string? Birthday { get; set; }
[J("https://www.w3.org/ns/activitystreams#endpoints")] [J($"{Constants.ActivityStreamsNs}#endpoints")]
[JC(typeof(ASEndpointsConverter))] [JC(typeof(ASEndpointsConverter))]
public ASEndpoints? Endpoints { get; set; } public ASEndpoints? Endpoints { get; set; }
[J("https://www.w3.org/ns/activitystreams#outbox")] [J($"{Constants.ActivityStreamsNs}#outbox")]
[JC(typeof(ASCollectionConverter))] [JC(typeof(ASCollectionConverter))]
public ASCollection<ASObject>? Outbox { get; set; } public ASCollection<ASObject>? Outbox { get; set; }
@ -72,27 +72,27 @@ public class ASActor : ASObject {
[JC(typeof(ASLinkConverter))] [JC(typeof(ASLinkConverter))]
public ASLink? Inbox { get; set; } public ASLink? Inbox { get; set; }
[J("https://www.w3.org/ns/activitystreams#followers")] [J($"{Constants.ActivityStreamsNs}#followers")]
[JC(typeof(ASCollectionConverter))] [JC(typeof(ASCollectionConverter))]
public ASCollection<ASObject>? Followers { get; set; } public ASCollection<ASObject>? Followers { get; set; }
[J("https://www.w3.org/ns/activitystreams#following")] [J($"{Constants.ActivityStreamsNs}#following")]
[JC(typeof(ASCollectionConverter))] [JC(typeof(ASCollectionConverter))]
public ASCollection<ASObject>? Following { get; set; } public ASCollection<ASObject>? Following { get; set; }
[J("https://www.w3.org/ns/activitystreams#sharedInbox")] [J($"{Constants.ActivityStreamsNs}#sharedInbox")]
[JC(typeof(ASLinkConverter))] [JC(typeof(ASLinkConverter))]
public ASLink? SharedInbox { get; set; } public ASLink? SharedInbox { get; set; }
[J("https://www.w3.org/ns/activitystreams#url")] [J($"{Constants.ActivityStreamsNs}#url")]
[JC(typeof(ASLinkConverter))] [JC(typeof(ASLinkConverter))]
public ASLink? Url { get; set; } public ASLink? Url { get; set; }
[J("https://www.w3.org/ns/activitystreams#movedTo")] [J($"{Constants.ActivityStreamsNs}#movedTo")]
[JC(typeof(ASLinkConverter))] [JC(typeof(ASLinkConverter))]
public ASLink? MovedTo { get; set; } public ASLink? MovedTo { get; set; }
[J("https://www.w3.org/ns/activitystreams#alsoKnownAs")] [J($"{Constants.ActivityStreamsNs}#alsoKnownAs")]
public List<ASLink>? AlsoKnownAs { get; set; } public List<ASLink>? AlsoKnownAs { get; set; }
[J("http://joinmastodon.org/ns#featured")] [J("http://joinmastodon.org/ns#featured")]
@ -103,19 +103,19 @@ public class ASActor : ASObject {
[JC(typeof(ASLinkConverter))] [JC(typeof(ASLinkConverter))]
public ASLink? FeaturedTags { get; set; } public ASLink? FeaturedTags { get; set; }
[J("https://www.w3.org/ns/activitystreams#icon")] [J($"{Constants.ActivityStreamsNs}#icon")]
[JC(typeof(ASImageConverter))] [JC(typeof(ASImageConverter))]
public ASImage? Avatar { get; set; } public ASImage? Avatar { get; set; }
[J("https://www.w3.org/ns/activitystreams#image")] [J($"{Constants.ActivityStreamsNs}#image")]
[JC(typeof(ASImageConverter))] [JC(typeof(ASImageConverter))]
public ASImage? Banner { get; set; } public ASImage? Banner { get; set; }
[J("https://w3id.org/security#publicKey")] [J($"{Constants.W3IdSecurityNs}#publicKey")]
[JC(typeof(ASPublicKeyConverter))] [JC(typeof(ASPublicKeyConverter))]
public ASPublicKey? PublicKey { get; set; } public ASPublicKey? PublicKey { get; set; }
public bool IsBot => Type == "https://www.w3.org/ns/activitystreams#Service"; public bool IsBot => Type == $"{Constants.ActivityStreamsNs}#Service";
public void Normalize(string uri, string acct) { public void Normalize(string uri, string acct) {
if (Type == null || !ActorTypes.Contains(Type)) throw new Exception("Actor is of invalid type"); if (Type == null || !ActorTypes.Contains(Type)) throw new Exception("Actor is of invalid type");

View file

@ -13,19 +13,19 @@ public class ASAttachment : ASObjectBase {
} }
public class ASDocument : ASAttachment { public class ASDocument : ASAttachment {
[J("https://www.w3.org/ns/activitystreams#url")] [J($"{Constants.ActivityStreamsNs}#url")]
[JC(typeof(ASObjectBaseConverter))] [JC(typeof(ASObjectBaseConverter))]
public ASObjectBase? Url { get; set; } public ASObjectBase? Url { get; set; }
[J("https://www.w3.org/ns/activitystreams#mediaType")] [J($"{Constants.ActivityStreamsNs}#mediaType")]
[JC(typeof(ValueObjectConverter))] [JC(typeof(ValueObjectConverter))]
public string? MediaType { get; set; } public string? MediaType { get; set; }
[J("https://www.w3.org/ns/activitystreams#sensitive")] [J($"{Constants.ActivityStreamsNs}#sensitive")]
[JC(typeof(ValueObjectConverter))] [JC(typeof(ValueObjectConverter))]
public bool? Sensitive { get; set; } public bool? Sensitive { get; set; }
[J("https://www.w3.org/ns/activitystreams#name")] [J($"{Constants.ActivityStreamsNs}#name")]
[JC(typeof(ValueObjectConverter))] [JC(typeof(ValueObjectConverter))]
public string? Description { get; set; } public string? Description { get; set; }
} }

View file

@ -1,3 +1,4 @@
using Iceshrimp.Backend.Core.Configuration;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using J = Newtonsoft.Json.JsonPropertyAttribute; using J = Newtonsoft.Json.JsonPropertyAttribute;
@ -11,11 +12,11 @@ public class ASCollection<T>() : ASObjectBase where T : ASObject {
Id = id; Id = id;
} }
[J("https://www.w3.org/ns/activitystreams#items")] [J($"{Constants.ActivityStreamsNs}#items")]
[JC(typeof(ASCollectionItemsConverter))] [JC(typeof(ASCollectionItemsConverter))]
public List<T>? Items { get; set; } public List<T>? Items { get; set; }
[J("https://www.w3.org/ns/activitystreams#totalItems")] [J($"{Constants.ActivityStreamsNs}#totalItems")]
[JC(typeof(VC))] [JC(typeof(VC))]
public long? TotalItems { get; set; } public long? TotalItems { get; set; }
} }

View file

@ -1,10 +1,11 @@
using Iceshrimp.Backend.Core.Configuration;
using J = Newtonsoft.Json.JsonPropertyAttribute; using J = Newtonsoft.Json.JsonPropertyAttribute;
using JC = Newtonsoft.Json.JsonConverterAttribute; using JC = Newtonsoft.Json.JsonConverterAttribute;
namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types;
public class ASEndpoints { public class ASEndpoints {
[J("https://www.w3.org/ns/activitystreams#sharedInbox")] [J($"{Constants.ActivityStreamsNs}#sharedInbox")]
[JC(typeof(ASObjectBaseConverter))] [JC(typeof(ASObjectBaseConverter))]
public ASObjectBase? SharedInbox { get; set; } public ASObjectBase? SharedInbox { get; set; }
} }

View file

@ -1,3 +1,4 @@
using Iceshrimp.Backend.Core.Configuration;
using J = Newtonsoft.Json.JsonPropertyAttribute; using J = Newtonsoft.Json.JsonPropertyAttribute;
using JC = Newtonsoft.Json.JsonConverterAttribute; using JC = Newtonsoft.Json.JsonConverterAttribute;
using VC = Iceshrimp.Backend.Core.Federation.ActivityStreams.Types.ValueObjectConverter; using VC = Iceshrimp.Backend.Core.Federation.ActivityStreams.Types.ValueObjectConverter;
@ -5,11 +6,11 @@ using VC = Iceshrimp.Backend.Core.Federation.ActivityStreams.Types.ValueObjectCo
namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types;
public class ASImage { public class ASImage {
[J("https://www.w3.org/ns/activitystreams#url")] [J($"{Constants.ActivityStreamsNs}#url")]
[JC(typeof(ASLinkConverter))] [JC(typeof(ASLinkConverter))]
public ASLink? Url { get; set; } public ASLink? Url { get; set; }
[J("https://www.w3.org/ns/activitystreams#sensitive")] [J($"{Constants.ActivityStreamsNs}#sensitive")]
[JC(typeof(VC))] [JC(typeof(VC))]
public bool? Sensitive { get; set; } public bool? Sensitive { get; set; }
} }

View file

@ -1,14 +1,15 @@
using Iceshrimp.Backend.Core.Configuration;
using J = Newtonsoft.Json.JsonPropertyAttribute; using J = Newtonsoft.Json.JsonPropertyAttribute;
using JC = Newtonsoft.Json.JsonConverterAttribute; using JC = Newtonsoft.Json.JsonConverterAttribute;
namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types;
public class ASLink(string url) : ASObjectBase(url) { public class ASLink(string url) : ASObjectBase(url) {
[J("https://www.w3.org/ns/activitystreams#href")] [J($"{Constants.ActivityStreamsNs}#href")]
[JC(typeof(ASObjectBaseConverter))] [JC(typeof(ASObjectBaseConverter))]
public ASObjectBase? Href { get; set; } public ASObjectBase? Href { get; set; }
[J("https://www.w3.org/ns/activitystreams#name")] [J($"{Constants.ActivityStreamsNs}#name")]
[JC(typeof(ValueObjectConverter))] [JC(typeof(ValueObjectConverter))]
public string? Name { get; set; } public string? Name { get; set; }

View file

@ -11,51 +11,51 @@ public class ASNote : ASObject {
[JC(typeof(VC))] [JC(typeof(VC))]
public string? MkContent { get; set; } public string? MkContent { get; set; }
[J("https://www.w3.org/ns/activitystreams#content")] [J($"{Constants.ActivityStreamsNs}#content")]
[JC(typeof(VC))] [JC(typeof(VC))]
public string? Content { get; set; } public string? Content { get; set; }
[J("https://www.w3.org/ns/activitystreams#url")] [J($"{Constants.ActivityStreamsNs}#url")]
[JC(typeof(ASLinkConverter))] [JC(typeof(ASLinkConverter))]
public ASLink? Url { get; set; } public ASLink? Url { get; set; }
[J("https://www.w3.org/ns/activitystreams#sensitive")] [J($"{Constants.ActivityStreamsNs}#sensitive")]
[JC(typeof(VC))] [JC(typeof(VC))]
public bool? Sensitive { get; set; } public bool? Sensitive { get; set; }
[J("https://www.w3.org/ns/activitystreams#published")] [J($"{Constants.ActivityStreamsNs}#published")]
[JC(typeof(VC))] [JC(typeof(VC))]
public DateTime? PublishedAt { get; set; } public DateTime? PublishedAt { get; set; }
[J("https://www.w3.org/ns/activitystreams#source")] [J($"{Constants.ActivityStreamsNs}#source")]
[JC(typeof(ASNoteSourceConverter))] [JC(typeof(ASNoteSourceConverter))]
public ASNoteSource? Source { get; set; } public ASNoteSource? Source { get; set; }
[J("https://www.w3.org/ns/activitystreams#to")] [J($"{Constants.ActivityStreamsNs}#to")]
public List<ASObjectBase> To { get; set; } = []; public List<ASObjectBase> To { get; set; } = [];
[J("https://www.w3.org/ns/activitystreams#cc")] [J($"{Constants.ActivityStreamsNs}#cc")]
public List<ASObjectBase> Cc { get; set; } = []; public List<ASObjectBase> Cc { get; set; } = [];
[J("https://www.w3.org/ns/activitystreams#attributedTo")] [J($"{Constants.ActivityStreamsNs}#attributedTo")]
public List<ASObjectBase> AttributedTo { get; set; } = []; public List<ASObjectBase> AttributedTo { get; set; } = [];
[J("https://www.w3.org/ns/activitystreams#inReplyTo")] [J($"{Constants.ActivityStreamsNs}#inReplyTo")]
[JC(typeof(ASObjectBaseConverter))] [JC(typeof(ASObjectBaseConverter))]
public ASObjectBase? InReplyTo { get; set; } public ASObjectBase? InReplyTo { get; set; }
[J("https://www.w3.org/ns/activitystreams#tag")] [J($"{Constants.ActivityStreamsNs}#tag")]
[JC(typeof(ASTagConverter))] [JC(typeof(ASTagConverter))]
public List<ASTag>? Tags { get; set; } public List<ASTag>? Tags { get; set; }
[J("https://www.w3.org/ns/activitystreams#attachment")] [J($"{Constants.ActivityStreamsNs}#attachment")]
[JC(typeof(ASAttachmentConverter))] [JC(typeof(ASAttachmentConverter))]
public List<ASAttachment>? Attachments { get; set; } public List<ASAttachment>? Attachments { get; set; }
public Note.NoteVisibility GetVisibility(ASActor actor) { public Note.NoteVisibility GetVisibility(ASActor actor) {
if (To.Any(p => p.Id == "https://www.w3.org/ns/activitystreams#Public")) if (To.Any(p => p.Id == $"{Constants.ActivityStreamsNs}#Public"))
return Note.NoteVisibility.Public; return Note.NoteVisibility.Public;
if (Cc.Any(p => p.Id == "https://www.w3.org/ns/activitystreams#Public")) if (Cc.Any(p => p.Id == $"{Constants.ActivityStreamsNs}#Public"))
return Note.NoteVisibility.Home; return Note.NoteVisibility.Home;
if (To.Any(p => p.Id is not null && p.Id == (actor.Followers?.Id ?? actor.Id + "/followers"))) if (To.Any(p => p.Id is not null && p.Id == (actor.Followers?.Id ?? actor.Id + "/followers")))
return Note.NoteVisibility.Followers; return Note.NoteVisibility.Followers;

View file

@ -1,3 +1,4 @@
using Iceshrimp.Backend.Core.Configuration;
using J = Newtonsoft.Json.JsonPropertyAttribute; using J = Newtonsoft.Json.JsonPropertyAttribute;
using JC = Newtonsoft.Json.JsonConverterAttribute; using JC = Newtonsoft.Json.JsonConverterAttribute;
using VC = Iceshrimp.Backend.Core.Federation.ActivityStreams.Types.ValueObjectConverter; using VC = Iceshrimp.Backend.Core.Federation.ActivityStreams.Types.ValueObjectConverter;
@ -5,11 +6,11 @@ using VC = Iceshrimp.Backend.Core.Federation.ActivityStreams.Types.ValueObjectCo
namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types;
public class ASNoteSource { public class ASNoteSource {
[J("https://www.w3.org/ns/activitystreams#content")] [J($"{Constants.ActivityStreamsNs}#content")]
[JC(typeof(VC))] [JC(typeof(VC))]
public string? Content { get; set; } public string? Content { get; set; }
[J("https://www.w3.org/ns/activitystreams#mediaType")] [J($"{Constants.ActivityStreamsNs}#mediaType")]
[JC(typeof(VC))] [JC(typeof(VC))]
public string? MediaType { get; set; } public string? MediaType { get; set; }
} }

View file

@ -1,8 +1,9 @@
using Iceshrimp.Backend.Core.Configuration;
using J = Newtonsoft.Json.JsonPropertyAttribute; using J = Newtonsoft.Json.JsonPropertyAttribute;
namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types;
public class ASOrderedCollection<T> : ASCollection<T> where T : ASObject { public class ASOrderedCollection<T> : ASCollection<T> where T : ASObject {
[J("https://www.w3.org/ns/activitystreams#orderedItems")] [J($"{Constants.ActivityStreamsNs}#orderedItems")]
public List<T>? OrderedItems { get; set; } public List<T>? OrderedItems { get; set; }
} }

View file

@ -1,3 +1,4 @@
using Iceshrimp.Backend.Core.Configuration;
using J = Newtonsoft.Json.JsonPropertyAttribute; using J = Newtonsoft.Json.JsonPropertyAttribute;
using JC = Newtonsoft.Json.JsonConverterAttribute; using JC = Newtonsoft.Json.JsonConverterAttribute;
using VC = Iceshrimp.Backend.Core.Federation.ActivityStreams.Types.ValueObjectConverter; using VC = Iceshrimp.Backend.Core.Federation.ActivityStreams.Types.ValueObjectConverter;
@ -5,11 +6,11 @@ using VC = Iceshrimp.Backend.Core.Federation.ActivityStreams.Types.ValueObjectCo
namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types;
public class ASPublicKey : ASObject { public class ASPublicKey : ASObject {
[J("https://w3id.org/security#owner")] [J($"{Constants.W3IdSecurityNs}#owner")]
[JC(typeof(ASObjectBaseConverter))] [JC(typeof(ASObjectBaseConverter))]
public ASObjectBase? Owner { get; set; } public ASObjectBase? Owner { get; set; }
[J("https://w3id.org/security#publicKeyPem")] [J($"{Constants.W3IdSecurityNs}#publicKeyPem")]
[JC(typeof(VC))] [JC(typeof(VC))]
public string? PublicKey { get; set; } public string? PublicKey { get; set; }
} }

View file

@ -13,11 +13,11 @@ public class ASTag : ASObjectBase {
} }
public class ASTagLink : ASTag { public class ASTagLink : ASTag {
[J("https://www.w3.org/ns/activitystreams#href")] [J($"{Constants.ActivityStreamsNs}#href")]
[JC(typeof(ASObjectBaseConverter))] [JC(typeof(ASObjectBaseConverter))]
public ASObjectBase? Href { get; set; } public ASObjectBase? Href { get; set; }
[J("https://www.w3.org/ns/activitystreams#name")] [J($"{Constants.ActivityStreamsNs}#name")]
[JC(typeof(ValueObjectConverter))] [JC(typeof(ValueObjectConverter))]
public string? Name { get; set; } public string? Name { get; set; }
} }

View file

@ -1,6 +1,7 @@
using System.Net; using System.Net;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using Iceshrimp.Backend.Core.Configuration;
using Iceshrimp.Backend.Core.Federation.ActivityStreams; using Iceshrimp.Backend.Core.Federation.ActivityStreams;
using Iceshrimp.Backend.Core.Helpers; using Iceshrimp.Backend.Core.Helpers;
using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Middleware;
@ -20,7 +21,7 @@ public static class LdSignature {
} }
public static async Task<bool> VerifyAsync(JObject activity, string key) { public static async Task<bool> VerifyAsync(JObject activity, string key) {
var options = activity["https://w3id.org/security#signature"]; var options = activity[$"{Constants.W3IdSecurityNs}#signature"];
if (options?.ToObject<SignatureOptions[]>() is not { Length: 1 } signatures) return false; if (options?.ToObject<SignatureOptions[]>() is not { Length: 1 } signatures) return false;
var signature = signatures[0]; var signature = signatures[0];
if (signature.Type is not ["_:RsaSignature2017"]) return false; if (signature.Type is not ["_:RsaSignature2017"]) return false;
@ -61,7 +62,7 @@ public static class LdSignature {
options.Signature = signature; options.Signature = signature;
activity.Add("https://w3id.org/security#signature", JToken.FromObject(options)); activity.Add($"{Constants.W3IdSecurityNs}#signature", JToken.FromObject(options));
return LdHelpers.Expand(activity)?[0] as JObject ?? return LdHelpers.Expand(activity)?[0] as JObject ??
throw new GracefulException(HttpStatusCode.UnprocessableEntity, "Failed to expand signed activity"); throw new GracefulException(HttpStatusCode.UnprocessableEntity, "Failed to expand signed activity");
@ -78,9 +79,9 @@ public static class LdSignature {
inputOptions.Remove("@id"); inputOptions.Remove("@id");
inputOptions.Remove("@type"); inputOptions.Remove("@type");
inputOptions.Remove("https://w3id.org/security#signatureValue"); inputOptions.Remove($"{Constants.W3IdSecurityNs}#signatureValue");
inputData.Remove("https://w3id.org/security#signature"); inputData.Remove($"{Constants.W3IdSecurityNs}#signature");
var canonicalData = LdHelpers.Canonicalize(inputData); var canonicalData = LdHelpers.Canonicalize(inputData);
var canonicalOptions = LdHelpers.Canonicalize(inputOptions); var canonicalOptions = LdHelpers.Canonicalize(inputOptions);
@ -94,7 +95,7 @@ public static class LdSignature {
private class SignatureOptions { private class SignatureOptions {
[J("@type")] public required List<string> Type { get; set; } [J("@type")] public required List<string> Type { get; set; }
[J("https://w3id.org/security#signatureValue")] [J($"{Constants.W3IdSecurityNs}#signatureValue")]
[JC(typeof(VC))] [JC(typeof(VC))]
public string? Signature { get; set; } public string? Signature { get; set; }
@ -102,15 +103,15 @@ public static class LdSignature {
[JC(typeof(VC))] [JC(typeof(VC))]
public string? Creator { get; set; } public string? Creator { get; set; }
[J("https://w3id.org/security#nonce", NullValueHandling = NullValueHandling.Ignore)] [J($"{Constants.W3IdSecurityNs}#nonce", NullValueHandling = NullValueHandling.Ignore)]
[JC(typeof(VC))] [JC(typeof(VC))]
public string? Nonce { get; set; } public string? Nonce { get; set; }
[J("https://w3id.org/security#domain", NullValueHandling = NullValueHandling.Ignore)] [J($"{Constants.W3IdSecurityNs}#domain", NullValueHandling = NullValueHandling.Ignore)]
[JC(typeof(VC))] [JC(typeof(VC))]
public string? Domain { get; set; } public string? Domain { get; set; }
[J("https://w3id.org/security#created", NullValueHandling = NullValueHandling.Ignore)] [J($"{Constants.W3IdSecurityNs}#created", NullValueHandling = NullValueHandling.Ignore)]
[JC(typeof(VC))] [JC(typeof(VC))]
//FIXME: is this valid? it should output datetime in ISO format //FIXME: is this valid? it should output datetime in ISO format
public DateTime? Created { get; set; } public DateTime? Created { get; set; }

View file

@ -1,4 +1,5 @@
using System.Security.Cryptography; using System.Security.Cryptography;
using Iceshrimp.Backend.Core.Configuration;
using Iceshrimp.Backend.Core.Federation.ActivityStreams; using Iceshrimp.Backend.Core.Federation.ActivityStreams;
using Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; using Iceshrimp.Backend.Core.Federation.ActivityStreams.Types;
using Iceshrimp.Backend.Core.Federation.Cryptography; using Iceshrimp.Backend.Core.Federation.Cryptography;
@ -53,7 +54,7 @@ public class LdSignatureTests {
var data = (_signed.DeepClone() as JObject)!; var data = (_signed.DeepClone() as JObject)!;
data.Should().NotBeNull(); data.Should().NotBeNull();
data.Remove("https://w3id.org/security#signature"); data.Remove($"{Constants.W3IdSecurityNs}#signature");
var verify = await LdSignature.VerifyAsync(data, _keypair.ExportRSAPublicKeyPem()); var verify = await LdSignature.VerifyAsync(data, _keypair.ExportRSAPublicKeyPem());
verify.Should().BeFalse(); verify.Should().BeFalse();
} }
@ -64,10 +65,10 @@ public class LdSignatureTests {
data.Should().NotBeNull(); data.Should().NotBeNull();
var signature = var signature =
data["https://w3id.org/security#signature"]?[0]?["https://w3id.org/security#signatureValue"]?[0]?["@value"]; data[$"{Constants.W3IdSecurityNs}#signature"]?[0]?[$"{Constants.W3IdSecurityNs}#signatureValue"]?[0]?["@value"];
signature.Should().NotBeNull(); signature.Should().NotBeNull();
data["https://w3id.org/security#signature"]![0]!["https://w3id.org/security#signatureValue"]![0]!["@value"] += data[$"{Constants.W3IdSecurityNs}#signature"]![0]![$"{Constants.W3IdSecurityNs}#signatureValue"]![0]!["@value"] +=
"test"; "test";
var e = await Assert.ThrowsExceptionAsync<FormatException>(async () => var e = await Assert.ThrowsExceptionAsync<FormatException>(async () =>
await LdSignature.VerifyAsync(data, await LdSignature.VerifyAsync(data,
@ -83,10 +84,10 @@ public class LdSignatureTests {
data.Should().NotBeNull(); data.Should().NotBeNull();
var creator = var creator =
data["https://w3id.org/security#signature"]?[0]?["http://purl.org/dc/terms/creator"]?[0]?["@value"]; data[$"{Constants.W3IdSecurityNs}#signature"]?[0]?["http://purl.org/dc/terms/creator"]?[0]?["@value"];
creator.Should().NotBeNull(); creator.Should().NotBeNull();
data["https://w3id.org/security#signature"]![0]!["http://purl.org/dc/terms/creator"]![0]!["@value"] += "test"; data[$"{Constants.W3IdSecurityNs}#signature"]![0]!["http://purl.org/dc/terms/creator"]![0]!["@value"] += "test";
var verify = await LdSignature.VerifyAsync(data, _keypair.ExportRSAPublicKeyPem()); var verify = await LdSignature.VerifyAsync(data, _keypair.ExportRSAPublicKeyPem());
verify.Should().BeFalse(); verify.Should().BeFalse();
} }