diff --git a/.gitignore b/.gitignore
index 13e13dd435fbfe8febcdb01de8f2410b7c9f92be..d3d3e50d719fc2a4b2e4fcb1de3ad08509bc147d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
 **/**notes.md
 
 private_notes/
+IntegrationTests/certificates
 
 ### VisualStudioCode template
 .vscode/*
diff --git a/BasicUnitTest/SecurityEventTokenTests.cs b/BasicUnitTest/SecurityEventTokenTests.cs
index ddddef9579bd34c02d80b3efa899cc57c4aad5a1..54bec9717b7d03ced31f7283256cec1ebb6a2d95 100644
--- a/BasicUnitTest/SecurityEventTokenTests.cs
+++ b/BasicUnitTest/SecurityEventTokenTests.cs
@@ -13,18 +13,28 @@ namespace BasicUnitTest;
 
 [TestFixture]
 public class SecurityEventTokenTests {
+
+    private const string rejectSubmission =
+        SecurityEventToken.RejectSubmissionSchema;
+
+    private FitEncryption _encryption = null!;
+
+    private const string acceptSubmission =
+        SecurityEventToken.AcceptSubmissionSchema;
+
+
     [SetUp]
     public void Setup() {
         var container = Container.Create();
         _encryption = new FitEncryption(container.Resolve<KeySet>(), null);
     }
 
-    private FitEncryption _encryption = null!;
+
 
     [Test]
     public void CreateJwt_AcceptSubmission() {
         var token = _encryption.CreateAcceptSecurityEventToken(new SubmissionForPickupDto {
-            SubmissionId = Guid.NewGuid().ToString(), CaseId = Guid.NewGuid().ToString(),
+            Id = Guid.NewGuid().ToString(), CaseId = Guid.NewGuid().ToString(),
             DestinationId = Guid.NewGuid().ToString()
         });
         Console.WriteLine(token);
diff --git a/BasicUnitTest/SenderTests.cs b/BasicUnitTest/SenderTests.cs
index ac5740fc719002b0b5c48af1a6dbb0c2fdff49fd..e824755cf22491380dab5cd161d3f1e15f6e3436 100644
--- a/BasicUnitTest/SenderTests.cs
+++ b/BasicUnitTest/SenderTests.cs
@@ -12,13 +12,19 @@ namespace BasicUnitTest;
 
 public class SenderTests {
     private IContainer _container = null!;
-    protected string clientId = "20175c2b-c4dd-4a01-99b1-3a08436881a1";
-    protected string clientSecret = "KV2qd7qc5n-xESB6dvfrTlMDx2BWHJd5hXJ6pKKnbEQ";
+    protected string clientId = null!;
+    protected string clientSecret = null!;
     private ILogger? logger;
+    private string leikaKey = null!;
 
     [OneTimeSetUp]
     public void OneTimeSetup() {
         _container = Container.Create();
+        logger = _container.Resolve<ILogger>();
+        var settings = _container.Resolve<MockSettings>();
+        clientId = settings.SenderClientId;
+        clientSecret = settings.SenderClientSecret;
+        leikaKey = settings.LeikaKey;
     }
 
     [SetUp]
@@ -46,7 +52,7 @@ public class SenderTests {
                 clientId, clientSecret,
                 Container.Create())
             .WithDestination(Guid.NewGuid().ToString())
-            .WithServiceType("", "urn:de:fim:leika:leistung:99400048079000")
+            .WithServiceType("", leikaKey)
             .WithAttachments(Array.Empty<Attachment>())
             .WithData("")
             .Submit();
@@ -58,7 +64,7 @@ public class SenderTests {
                 clientId, clientSecret,
                 Container.Create())
             .WithDestination(Guid.NewGuid().ToString())
-            .WithServiceType("", "urn:de:fim:leika:leistung:99400048079000")
+            .WithServiceType("", leikaKey)
             .WithAttachments(Array.Empty<Attachment>())
             .Submit();
     }
@@ -67,7 +73,7 @@ public class SenderTests {
     public void VerifyMetaData_ValidData_Fine() {
         // Arrange
         var submission = new Submission();
-        submission.ServiceType.Identifier = "urn:de:fim:leika:leistung:99400048079000";
+        submission.ServiceType.Identifier = leikaKey;
 
         // Act
         var metadata = Sender.CreateMetadata(submission);
@@ -82,7 +88,6 @@ public class SenderTests {
     public void VerifyMetaData_MissingLeikaKey_ThorwsAnError() {
         // Arrange
         var submission = new Submission();
-        //submission.ServiceType.Identifier = "urn:de:fim:leika:leistung:99400048079000";
 
         // Act
         var metadata = Sender.CreateMetadata(submission);
diff --git a/DemoRunner/DemoRunner.csproj b/DemoRunner/DemoRunner.csproj
index 1e670320d5da6e923c6e02273e721b38128fafd4..ac77d58532b65d9b7ac13e46f81cec6b37a0afe4 100644
--- a/DemoRunner/DemoRunner.csproj
+++ b/DemoRunner/DemoRunner.csproj
@@ -10,11 +10,11 @@
     </PropertyGroup>
 
     <ItemGroup>
-        <PackageReference Include="FitConnect" Version="0.0.1-beta.2"/>
-        <PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0"/>
-        <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0"/>
-        <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0"/>
-        <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0"/>
+        <PackageReference Include="FitConnect" Version="0.0.1-beta.2" />
+        <PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
+        <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
+        <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
+        <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
     </ItemGroup>
 
     <ItemGroup>
@@ -42,7 +42,7 @@
     </ItemGroup>
 
     <ItemGroup>
-        <ProjectReference Include="..\FitConnect\FitConnect.csproj"/>
+        <ProjectReference Include="..\FitConnect\FitConnect.csproj" />
     </ItemGroup>
 
 </Project>
diff --git a/DemoRunner/SubscriberDemo.cs b/DemoRunner/SubscriberDemo.cs
index d08b9f6e51ed37bf55be0d21a7a410b1ca101399..5a8c96bd75a1f464731e43a92f13e9932fa9f6ee 100644
--- a/DemoRunner/SubscriberDemo.cs
+++ b/DemoRunner/SubscriberDemo.cs
@@ -33,7 +33,7 @@ public static class SubscriberDemo {
         foreach (var submission in submissions)
             try {
                 var subscriberWithSubmission =
-                    subscriber.RequestSubmission(submission.SubmissionId);
+                    subscriber.RequestSubmission(submission.Id);
                 var attachments = subscriberWithSubmission
                     .GetAttachments();
 
diff --git a/DemoRunner/appsettings.json.template b/DemoRunner/appsettings.json.template
index a3c1adeacf97b9b3d0bb8752ccd19934ef7d8cf6..22d1b2e054b134a606deab61659be4b4a24f0f9c 100644
--- a/DemoRunner/appsettings.json.template
+++ b/DemoRunner/appsettings.json.template
@@ -3,6 +3,7 @@
     "Sender": {
       "ClientId": "00000000-0000-0000-0000-000000000000",
       "ClientSecret": "",
+      "DestinationId": "00000000-0000-0000-0000-000000000000",
       "LeikaKey": "urn:de:fim:leika:leistung:99400048079000"
     },
     "Subscriber": {
diff --git a/Documentation/documentation.de-DE.md b/Documentation/documentation.de-DE.md
index 24fb1aab9576d4eff7efe71eb64cb18695d72a76..6933d0a820563490681d10d26b9b9c1eb8039644 100644
--- a/Documentation/documentation.de-DE.md
+++ b/Documentation/documentation.de-DE.md
@@ -8,6 +8,15 @@ Das FIT-Connect .NET SDK bietet eine einfache Möglichkeit, sowohl einen Antrags
 
 ### OSX
 
+__Anmerkung:__
+Bei einem Mac mit einem M1 chip, muss brew in der _x86-64_-Version installiert werden.
+
+_Die Version x86_64 kann parallel zur arm64 Version installiert werden._
+
+```sh
+arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+```
+
 Auf OSX wird das SDK nur dann unterstützt, wenn OpenSSL auf dem System installiert ist.
 
 ```sh
diff --git a/E2ETest/RejectSubmissionTest.cs b/E2ETest/RejectSubmissionTest.cs
index f69713c5a1e5a8650702273e822cf10ba215b0b4..393084aae66ca071b098a01bb32d1e3fb3ce50f8 100644
--- a/E2ETest/RejectSubmissionTest.cs
+++ b/E2ETest/RejectSubmissionTest.cs
@@ -6,7 +6,7 @@ using Microsoft.Extensions.Logging;
 namespace E2ETest;
 
 public class RejectSubmissionTest : EndToEndTestBase {
-    private string _caseId = null!;
+    private string _caseId  = null!;
     private string _submissionId = null!;
 
     [Order(10)]
diff --git a/E2ETest/StraightForwardTest.cs b/E2ETest/StraightForwardTest.cs
index 0eb0df15fcf30a010be572d890acfdf1a7c1713e..19a3000b38c5d3a3d60fa82ef2dfff4c3d6f50e4 100644
--- a/E2ETest/StraightForwardTest.cs
+++ b/E2ETest/StraightForwardTest.cs
@@ -47,7 +47,7 @@ public class StraightForwardTest : EndToEndTestBase {
         status.ForEach(
             s => Logger.LogInformation("Status {When} {Event}", s.EventTime, s.EventType));
     }
-
+    
     [Test]
     [Order(40)]
     public void RequestSubmission() {
diff --git a/FitConnect/Encryption/CertificateHelper.cs b/FitConnect/Encryption/CertificateHelper.cs
new file mode 100644
index 0000000000000000000000000000000000000000..691a54eff175c575a9ebbb5546f22f6bc1901114
--- /dev/null
+++ b/FitConnect/Encryption/CertificateHelper.cs
@@ -0,0 +1,98 @@
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Text.Unicode;
+using Microsoft.Extensions.Logging;
+using Microsoft.IdentityModel.Tokens;
+using Microsoft.Win32.SafeHandles;
+using Newtonsoft.Json;
+
+namespace FitConnect.Encryption;
+
+public class CertificateHelper {
+    private readonly ILogger? _logger;
+
+    public CertificateHelper(ILogger? logger = null) {
+        _logger = logger;
+    }
+
+    internal bool ValidateCertificate(string keyJson, LogLevel logLevel,
+        X509Certificate2[]? rootCertificate = null) =>
+        ValidateCertificate(new JsonWebKey(keyJson), logLevel, rootCertificate);
+
+    internal bool ValidateCertificate(X509Certificate2 certificate,
+        out X509ChainStatus[] chainStatus,
+        X509Certificate2[]? rootCertificate = null,
+        LogLevel logLevel = LogLevel.Warning) {
+        var certificateChain = new X509Chain();
+
+//        certificate.ExportToPem($"./temp/{Guid.NewGuid().ToString()}");
+        _logger?.LogDebug("Issuers: {Issuer}", certificate.Issuer);
+
+        if (rootCertificate != null) {
+            certificateChain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
+            certificateChain.ChainPolicy.CustomTrustStore.AddRange(rootCertificate);
+            certificateChain.ChainPolicy.ExtraStore.AddRange(rootCertificate);
+            certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
+            certificateChain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
+            certificateChain.ChainPolicy.DisableCertificateDownloads = false;
+            // certificateChain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreEndRevocationUnknown;
+            certificateChain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
+            _logger?.LogDebug("Using custom root certificate");
+        }
+        else {
+            certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
+            certificateChain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
+            certificateChain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
+            certificateChain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 30);
+        }
+
+
+        var result = certificateChain.Build(certificate);
+
+        chainStatus = certificateChain.ChainStatus
+            .Where(s => s.Status != X509ChainStatusFlags.PartialChain).ToArray();
+
+        var statusAggregation = certificateChain.ChainStatus.Aggregate("",
+            (r, s) => r + "\n\t - " + s.Status + ": " + s.StatusInformation);
+
+        if (certificateChain.ChainStatus.Length > 0)
+            _logger?.Log(logLevel, "Certificate status: {ObjStatusInformation}",
+                statusAggregation);
+
+        return result;
+    }
+
+    internal bool ValidateCertificate(JsonWebKey key, LogLevel logLevel = LogLevel.Error,
+        X509Certificate2[]? root = null) {
+        var certificates = key.X5c.Select(s => new X509Certificate2(Convert.FromBase64String(s)))
+            .ToList();
+
+        // if (certificates.Count != 3) {
+        //     _logger?.Log(logLevel, "Found {Count} certificate(s) but should be 3",
+        //         certificates.Count);
+        //     return false;
+        // }
+        // root ??= new X509Certificate2(Convert.FromBase64String(key.X5t));
+
+        var valid = certificates.Aggregate(true,
+            (result, cert) => result
+                              && ValidateCertificate(cert, out _, root, logLevel)
+            // && cert.Verify()
+        );
+        return valid;
+    }
+}
+
+public static class X509Certificate2Extensions {
+    public static void ExportToPem(this X509Certificate2 certificate, string fileName) {
+        StringBuilder builder = new StringBuilder();
+        builder.AppendLine("-----BEGIN CERTIFICATE-----");
+        builder.AppendLine(
+            Convert.ToBase64String(certificate.RawData, Base64FormattingOptions.InsertLineBreaks));
+        builder.AppendLine("-----END CERTIFICATE-----");
+        var content = builder.ToString();
+
+        File.WriteAllText(fileName + ".pem", content);
+        File.WriteAllText(fileName + ".json", JsonConvert.SerializeObject(certificate));
+    }
+}
diff --git a/FitConnect/Encryption/FitEncryption.cs b/FitConnect/Encryption/FitEncryption.cs
index 6061f0f5b8642a59677652225706ab8dc099e199..4975ed142f25316c18ce1b3f94aecfe7e4ca9d20 100644
--- a/FitConnect/Encryption/FitEncryption.cs
+++ b/FitConnect/Encryption/FitEncryption.cs
@@ -1,6 +1,7 @@
 using System.IdentityModel.Tokens.Jwt;
 using System.Security.Cryptography;
 using System.Text;
+using FitConnect.Models;
 using FitConnect.Models.v1.Api;
 using FitConnect.Services.Models.v1.Submission;
 using IdentityModel;
@@ -21,6 +22,10 @@ public class FitEncryption {
     private readonly IEncryptor _encryptor = new JoseEncryptor();
     private readonly ILogger? _logger;
     private JwtHeader? _jwtHeader;
+    public string? PrivateKeyDecryption { get; set; }
+    public string? PrivateKeySigning { get; set; }
+    public string? PublicKeyEncryption { get; set; }
+    public string? PublicKeySignatureVerification { get; set; }
 
     internal FitEncryption(ILogger? logger) {
         _logger = logger;
@@ -44,11 +49,6 @@ public class FitEncryption {
         PublicKeySignatureVerification = keySet.PublicKeySignatureVerification;
     }
 
-    public string? PrivateKeyDecryption { get; set; }
-    public string? PrivateKeySigning { get; set; }
-    public string? PublicKeyEncryption { get; set; }
-    public string? PublicKeySignatureVerification { get; set; }
-
 
     public (string plainText, byte[] plainBytes, byte[] tag)
         Decrypt(string cypherText, string key) {
@@ -93,31 +93,50 @@ public class FitEncryption {
             new { problems = problemsArray });
     }
 
-    public string CreateAcceptSecurityEventToken(SubmissionForPickupDto submission) {
-        // string submissionSubmissionId,string submissionCaseId, string submissionDestinationId) {
-
-        #warning Dummy data is used for testing purposes, replace with actual data
-        // NOMERGE Remove Dummy data
-        var payload = new {
-            authenticationTags = new {
-                data = "UCGiqJxhBI3IFVdPalHHvA", metadata = "XFBoMYUZodetZdvTiFvSkQ",
-                attachments = new Dictionary<string, string> {
-                    { "0b799252-deb9-42b0-98d3-c50d24bbafe0", "rT99rwrBTbTI7IJM8fU3El" }
+    private dynamic GenerateAuthenticationTags(Submission submission) {
+        _logger?.LogInformation("Generating authentication tags");
+        var attachmentDictionary = new Dictionary<string, string>();
+        submission.Attachments.ForEach(a =>
+            attachmentDictionary.Add(a.Id, a.AttachmentAuthentication!));
+
+        if (submission.Data != null)
+            return new {
+                authenticationTags = new {
+                    data = submission.DataAuthentication,
+                    metadata = submission.MetaAuthentication,
+                    attachments = attachmentDictionary
                 }
+            };
+        return new {
+            authenticationTags = new {
+                metadata = submission.MetaAuthentication,
+                attachments = attachmentDictionary
             }
         };
+    }
+
 
-        // NOMERGE Add payload 
-        if (submission?.SubmissionId == null || submission?.CaseId == null ||
-            submission?.DestinationId == null)
+    public string CreateAcceptSecurityEventToken(SubmissionForPickupDto submission,
+        dynamic? payload = null) {
+        if (submission?.Id == null || submission?.CaseId == null ||
+            submission?.DestinationId == null) {
             throw new ArgumentException("SubmissionId, CaseId and DestinationId are required");
+        }
 
-        return CreateSecurityEventToken(submission.SubmissionId, submission.CaseId,
+        return CreateSecurityEventToken(submission.Id, submission.CaseId,
             submission.DestinationId,
             "https://schema.fitko.de/fit-connect/events/accept-submission", null);
     }
 
 
+    public string CreateAcceptSecurityEventToken(Submission submission) {
+        var payload = GenerateAuthenticationTags(submission);
+        return CreateSecurityEventToken(submission.Id, submission.CaseId,
+            submission.DestinationId,
+            "https://schema.fitko.de/fit-connect/events/accept-submission", payload);
+    }
+
+
     private string CreateSecurityEventToken(string submissionId,
         string caseId,
         string destinationId,
@@ -179,6 +198,10 @@ public class FitEncryption {
         return ByteToHexString(SHA512.Create().ComputeHash(Encoding.UTF8.GetBytes(data)));
     }
 
+    public static string CalculateHash(byte[] data) {
+        return ByteToHexString(SHA512.Create().ComputeHash(data));
+    }
+
     private static string ByteToHexString(IEnumerable<byte> data) {
         var sb = new StringBuilder();
         foreach (var b in data) sb.Append(b.ToString("x2"));
@@ -247,4 +270,4 @@ public class FitEncryption {
 
         return result.IsValid;
     }
-}
+}
\ No newline at end of file
diff --git a/FitConnect/FitConnect.csproj b/FitConnect/FitConnect.csproj
index c131e6d93b08c118aba6c431caebe62b8a071bfd..c4077619411f1911413c68b3bb5023ffd09bc28a 100644
--- a/FitConnect/FitConnect.csproj
+++ b/FitConnect/FitConnect.csproj
@@ -11,28 +11,28 @@
     </PropertyGroup>
 
     <ItemGroup>
-        <PackageReference Include="Autofac" Version="6.4.0"/>
-        <PackageReference Include="IdentityModel" Version="6.0.0"/>
-        <PackageReference Include="jose-jwt" Version="4.0.0"/>
-        <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0"/>
-        <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.1"/>
-        <PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="6.22.0"/>
-        <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.22.0"/>
-        <PackageReference Include="Newtonsoft.Json" Version="13.0.1"/>
-        <PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.14"/>
-        <PackageReference Include="NJsonSchema" Version="10.7.2"/>
-        <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.21.0"/>
+        <PackageReference Include="Autofac" Version="6.4.0" />
+        <PackageReference Include="IdentityModel" Version="6.0.0" />
+        <PackageReference Include="jose-jwt" Version="4.0.0" />
+        <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
+        <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.1" />
+        <PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="6.22.0" />
+        <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.22.0" />
+        <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
+        <PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.14" />
+        <PackageReference Include="NJsonSchema" Version="10.7.2" />
+        <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.21.0" />
     </ItemGroup>
 
     <ItemGroup>
-        <None Remove="metadata.schema.json"/>
-        <EmbeddedResource Include="metadata.schema.json"/>
+        <None Remove="metadata.schema.json" />
+        <EmbeddedResource Include="metadata.schema.json" />
     </ItemGroup>
 
     <ItemGroup>
-        <Compile Remove="FunctionalBaseClass.cs"/>
-        <Compile Remove="Models\OAuthAccessToken.cs"/>
-        <Compile Remove="DiContainer.cs"/>
+        <Compile Remove="FunctionalBaseClass.cs" />
+        <Compile Remove="Models\OAuthAccessToken.cs" />
+        <Compile Remove="DiContainer.cs" />
     </ItemGroup>
 
 </Project>
diff --git a/FitConnect/FitConnectClient.cs b/FitConnect/FitConnectClient.cs
index a46e63e14b482179d379e803171d5e0d24f27378..19089979576abe25e29fb04b368216e49d167689 100644
--- a/FitConnect/FitConnectClient.cs
+++ b/FitConnect/FitConnectClient.cs
@@ -15,6 +15,7 @@ public abstract class FitConnectClient {
     private readonly string? _privateKeySigning;
     private readonly string? _publicKeyEncryption;
     private readonly string? _publicKeySignatureVerification;
+    protected readonly bool VerifiedKeysAreMandatory;
 
 
     protected FitConnectClient(FitConnectEnvironment environment,
@@ -41,6 +42,7 @@ public abstract class FitConnectClient {
         DestinationService =
             new DestinationService(environment.SubmissionUrl[0], OAuthService, logger: logger);
         Logger = logger;
+        VerifiedKeysAreMandatory = environment.VerifiedKeysAreMandatory;
     }
 
     protected FitConnectClient(FitConnectEnvironment environment,
@@ -115,8 +117,9 @@ public abstract class FitConnectClient {
     /// <returns></returns>
     public List<SecurityEventToken> GetStatusForSubmission(SubmissionForPickupDto submission,
         bool skipTest = false) {
-        if (submission?.CaseId == null || submission.DestinationId == null)
+        if (submission?.CaseId == null || submission.DestinationId == null) {
             throw new ArgumentNullException(nameof(submission));
+        }
 
         var events = SubmissionService
             .GetStatusForSubmissionAsync(submission.CaseId, submission.DestinationId, skipTest)
diff --git a/FitConnect/Interfaces/IFitConnectClient.cs b/FitConnect/Interfaces/IFitConnectClient.cs
index 7e25169e1ccffac20e4115d9a0e769f8a376c64b..d27dc7f9f2c5e898ae05859e98f45f6a68c45c3b 100644
--- a/FitConnect/Interfaces/IFitConnectClient.cs
+++ b/FitConnect/Interfaces/IFitConnectClient.cs
@@ -17,6 +17,7 @@ public interface IFitConnectClient {
         bool skipTest = false);
 
     /// <summary>
+    /// 
     /// </summary>
     /// <param name="submission"></param>
     /// <param name="skipTest"></param>
diff --git a/FitConnect/Interfaces/Subscriber/ISubscriber.cs b/FitConnect/Interfaces/Subscriber/ISubscriber.cs
index 2f6c2489409826aafe2847d9413a3fef07541359..2f3b0520aa008b362a9b4d71cbd4d9953ffc64e6 100644
--- a/FitConnect/Interfaces/Subscriber/ISubscriber.cs
+++ b/FitConnect/Interfaces/Subscriber/ISubscriber.cs
@@ -20,6 +20,6 @@ public interface ISubscriber : IFitConnectClient {
     /// <param name="submissionId">unique identifier of a <see cref="Submission" /></param>
     /// <param name="skipSchemaTest"></param>
     /// <returns>A subscriber object with a submission</returns>
-    public ISubscriberWithSubmission RequestSubmission(string? submissionId,
+    public ISubscriberWithSubmission RequestSubmission(string submissionId,
         bool skipSchemaTest = false);
 }
diff --git a/FitConnect/Interfaces/Subscriber/ISubscriberWithSubmission.cs b/FitConnect/Interfaces/Subscriber/ISubscriberWithSubmission.cs
index 6d82850af24e57431622e8f8a80cc54f900f903c..c7cd242a8b95c98145a98ff751ddb6a6600719b3 100644
--- a/FitConnect/Interfaces/Subscriber/ISubscriberWithSubmission.cs
+++ b/FitConnect/Interfaces/Subscriber/ISubscriberWithSubmission.cs
@@ -1,9 +1,10 @@
 using FitConnect.Models;
 using FitConnect.Models.v1.Api;
+using FitConnect.Services.Models;
 
 namespace FitConnect.Interfaces.Subscriber;
 
-public interface ISubscriberWithSubmission {
+public interface ISubscriberWithSubmission : WithSubmission {
     public Submission? Submission { get; }
 
     /// <summary>
@@ -42,3 +43,12 @@ public interface ISubscriberWithSubmission {
     /// <param name="status">state the submission has to be set to</param>
     public void CompleteSubmission(FinishSubmissionStatus status);
 }
+
+public interface WithSubmission {
+    /// <summary>
+    /// Verifies the submission acceptance status
+    /// </summary>
+    /// <param name="acceptanceStatus"></param>
+    /// <returns></returns>
+    public bool VerifyStatus(AcceptanceStatus acceptanceStatus);
+}
diff --git a/FitConnect/Models/Attachment.cs b/FitConnect/Models/Attachment.cs
index 86ed85f32c0fdafc7a38b9c8c001b08b88fceb1e..88cdc74a7c7f13e0279dd7f47f13f441c8b8cfa9 100644
--- a/FitConnect/Models/Attachment.cs
+++ b/FitConnect/Models/Attachment.cs
@@ -5,9 +5,10 @@ using FitConnect.Models.Api.Metadata;
 namespace FitConnect.Models;
 
 public class Attachment {
-    public Attachment(Api.Metadata.Attachment metadata, byte[] content) {
+    public Attachment(Api.Metadata.Attachment metadata, byte[] content, string attachmentAuthentication) {
         Filename = metadata.Filename;
         Content = content;
+        AttachmentAuthentication = attachmentAuthentication;
         MimeType = Path.GetExtension(metadata.Filename) switch {
             "pdf" => "application/pdf",
             "xml" => "application/xml",
@@ -43,6 +44,7 @@ public class Attachment {
     public string Id { get; } = Guid.NewGuid().ToString();
 
     public byte[]? Content { get; init; }
+    public string? AttachmentAuthentication { get; }
 
     public string? Hash => CalculateHash();
 
diff --git a/FitConnect/Models/Callback.cs b/FitConnect/Models/Callback.cs
index 9794d32f12ad89f8ff1f6ed135b6b3de411b56ca..9e77458289dd2b29cef838f3fe1199b1accbc429 100644
--- a/FitConnect/Models/Callback.cs
+++ b/FitConnect/Models/Callback.cs
@@ -3,9 +3,8 @@ using FitConnect.Services.Models;
 namespace FitConnect.Models;
 
 public record Callback(string? Url, string? Secret) {
-    public static explicit operator Callback(CallbackDto dto) {
-        return new(dto.Url, null);
-    }
+    public static explicit operator Callback(CallbackDto dto) 
+        => new(dto.Url, null);
 
     public static explicit operator CallbackDto(Callback model) {
         return new CallbackDto { Url = model.Url };
diff --git a/FitConnect/Models/FitConnectEnvironment.cs b/FitConnect/Models/FitConnectEnvironment.cs
index 294cf80468e440db3aadfea90c00548fbb0fc195..fd377f512e52e9f507a0deb46d3355522337d847 100644
--- a/FitConnect/Models/FitConnectEnvironment.cs
+++ b/FitConnect/Models/FitConnectEnvironment.cs
@@ -4,25 +4,32 @@ public class FitConnectEnvironment {
     // List of Domains
     // https://wiki.fit-connect.fitko.dev/de/Betrieb/Dokumentation/Domains
 
+    public static readonly FitConnectEnvironment Develop = new(
+        "https://auth-dev.fit-connect.fitko.dev/token",
+        new[] { "https://submission-api-dev.fit-connect.fitko.dev" },
+        string.Empty, // "https://routing-api-testing.fit-connect.fitko.dev", // Dev does not have a routing API
+        "https://portal.auth-dev.fit-connect.fitko.dev"
+    ) { VerifiedKeysAreMandatory = false };
+
     public static readonly FitConnectEnvironment Testing = new(
         "https://auth-testing.fit-connect.fitko.dev/token",
         new[] { "https://submission-api-testing.fit-connect.fitko.dev" },
         "https://routing-api-testing.fit-connect.fitko.dev",
         "https://portal.auth-testing.fit-connect.fitko.dev"
-    );
+    ) { VerifiedKeysAreMandatory = false };
 
     public static readonly FitConnectEnvironment Staging = new(
-        "https://auth-refz.fit-connect.fitko.dev/token",
-        new[] { "https://submission-api-refz.fit-connect.fitko.dev" },
-        "https://routing-api-refz.fit-connect.fitko.dev",
-        "https://portal.auth-refz.fit-connect.fitko.dev"
+        "https://auth-refz.fit-connect.fitko.net/token",
+        new[] { "submission-api-refz.fit-connect.niedersachsen.de" },
+        string.Empty, // "https://routing-api-testing.fit-connect.fitko.dev", // Stage does not have a routing API
+        "https://portal.auth-refz.fit-connect.fitko.net"
     );
 
     public static readonly FitConnectEnvironment Production = new(
-        "https://auth.fit-connect.fitko.net/token",
-        new[] { "https://submission-api.fit-connect.fitko.net" },
-        "https://routing-api.fit-connect.fitko.net",
-        "https://portal.auth.fit-connect.fitko.net"
+        "https://auth-prod.fit-connect.fitko.net/token",
+        new[] { "https://submission-api-prod.fit-connect.niedersachsen.de" },
+        "https://routing-api-prod.fit-connect.fitko.net",
+        "https://portal.auth-prod.fit-connect.fitko.net"
     );
 
     public FitConnectEnvironment(string sspUrl, string tokenUrl, string[] submissionUrl,
@@ -67,6 +74,8 @@ public class FitConnectEnvironment {
     /// </summary>
     public string RoutingUrl { get; }
 
+    public bool VerifiedKeysAreMandatory { get; private init; } = true;
+
     /// <summary>
     ///     Creates the endpoints for the given environment.
     /// </summary>
diff --git a/FitConnect/Models/SecurityEventToken.cs b/FitConnect/Models/SecurityEventToken.cs
index 02204d91b8d5bd5988696f71eda6768bb76b662c..de3b3ec1000f0dd55eafb8e7101134256034c753 100644
--- a/FitConnect/Models/SecurityEventToken.cs
+++ b/FitConnect/Models/SecurityEventToken.cs
@@ -18,16 +18,36 @@ public enum EventType {
 }
 
 public class SecurityEventToken {
-    private const string Accept = "https://schema.fitko.de/fit-connect/events/accept-submission";
-    private const string Reject = "https://schema.fitko.de/fit-connect/events/reject-submission";
+
+    public const string CreateSubmissionSchema =
+        "https://schema.fitko.de/fit-connect/events/create-submission";
+
+    public const string SubmitSubmissionSchema =
+        "https://schema.fitko.de/fit-connect/events/submit-submission";
+
+    public const string NotifySubmissionSchema =
+        "https://schema.fitko.de/fit-connect/events/notify-submission";
+
+    public const string ForwardSubmissionSchema =
+        "https://schema.fitko.de/fit-connect/events/forward-submission";
+
+    public const string RejectSubmissionSchema =
+        "https://schema.fitko.de/fit-connect/events/reject-submission";
+
+    public const string AcceptSubmissionSchema =
+        "https://schema.fitko.de/fit-connect/events/accept-submission";
+
+    public const string DeleteSubmissionSchema =
+        "https://schema.fitko.de/fit-connect/events/delete-submission";
+
 
     public SecurityEventToken(string jwtEncodedString) {
         Token = new JsonWebToken(jwtEncodedString);
         EventType = DecodeEventType(Token.Claims);
 
-        if (Token.Claims.All(c => c.Type != "iat"))
+        if (Token.Claims.All(c => c.Type != "iat")) 
             return;
-
+        
         var iat = Token.Claims.FirstOrDefault(c => c.Type == "iat")!.Value;
         if (long.TryParse(iat, out var timeEpoch))
             EventTime = DateTime.UnixEpoch.AddSeconds(timeEpoch);
@@ -52,30 +72,36 @@ public class SecurityEventToken {
 
         var contentData = JsonConvert.DeserializeObject(eventsClaim.Value);
 
-
         if (eventsClaim.Value.Contains(
-                "https://schema.fitko.de/fit-connect/events/create-submission"))
+                CreateSubmissionSchema))
             return EventType.Create;
 
         if (eventsClaim.Value.Contains(
-                "https://schema.fitko.de/fit-connect/events/submit-submission"))
+                SubmitSubmissionSchema))
             return EventType.Submit;
 
         if (eventsClaim.Value.Contains(
-                "https://schema.fitko.de/fit-connect/events/notify-submission"))
+                NotifySubmissionSchema))
             return EventType.Notify;
         if (eventsClaim.Value.Contains(
-                "https://schema.fitko.de/fit-connect/events/forward-submission"))
+                ForwardSubmissionSchema))
             return EventType.Forward;
-        if (eventsClaim.Value.Contains(Reject)) {
+        if (eventsClaim.Value.Contains(
+
+                RejectSubmissionSchema)) {
             Problems = GetProblems(events?.Values?.FirstOrDefault()?.ToString() ?? "");
             return EventType.Reject;
         }
 
-        if (eventsClaim.Value.Contains(Accept)) return EventType.Accept;
+
+
+        if (eventsClaim.Value.Contains(AcceptSubmissionSchema))
+
+            return EventType.Accept;
+
 
         if (eventsClaim.Value.Contains(
-                "https://schema.fitko.de/fit-connect/events/delete-submission"))
+                DeleteSubmissionSchema))
             return EventType.Delete;
 
         return EventType.NotSet;
diff --git a/FitConnect/Models/Submission.cs b/FitConnect/Models/Submission.cs
index bd9b20e8dbba5e95beaeaa7f32d5ab49e0a52aef..b8792a1d46a3790e20986c32dc9b4a42afad5ee0 100644
--- a/FitConnect/Models/Submission.cs
+++ b/FitConnect/Models/Submission.cs
@@ -1,11 +1,12 @@
+using System.Security.Cryptography.X509Certificates;
 using FitConnect.Services.Models;
 using FitConnect.Services.Models.v1.Submission;
 
 namespace FitConnect.Models;
 
 public class Submission {
-    public string? Id { get; set; }
-    public string? CaseId { get; set; }
+    public string Id { get; set; } = null!;
+    public string CaseId { get; set; } = null!;
     public Destination Destination { get; set; } = new();
 
     public string DestinationId {
@@ -23,6 +24,8 @@ public class Submission {
     public string? Data { get; set; }
     public string? EncryptedMetadata { get; set; }
     public string? EncryptedData { get; set; }
+    public string? MetaAuthentication => EncryptedMetadata?.Split('.').Last();
+    public string? DataAuthentication => EncryptedData?.Split('.').Last();
 
     public bool IsSubmissionReadyToAdd(out string? error) {
         var innerError = "";
@@ -45,7 +48,7 @@ public class Submission {
 
     public static implicit operator SubmissionForPickupDto(Submission sub) {
         return new SubmissionForPickupDto {
-            SubmissionId = sub.Id,
+            Id = sub.Id,
             CaseId = sub.CaseId,
             DestinationId = sub.DestinationId
         };
@@ -53,7 +56,7 @@ public class Submission {
 
     public static explicit operator Submission(SubmissionForPickupDto dto) {
         return new Submission {
-            Id = dto.SubmissionId,
+            Id = dto.Id,
             Callback = null,
             DestinationId = dto.DestinationId ??
                             throw new NullReferenceException(nameof(dto.DestinationId)),
diff --git a/FitConnect/Router.cs b/FitConnect/Router.cs
index 9f211eb2361c64e39151619bc9705b9f323477e0..51d28dce0aa17511d9579d3b545cf1dde2dee3d9 100644
--- a/FitConnect/Router.cs
+++ b/FitConnect/Router.cs
@@ -1,4 +1,4 @@
-using System.Text;
+using System.Text;
 using FitConnect.Encryption;
 using FitConnect.Models;
 using FitConnect.Services;
@@ -13,7 +13,7 @@ using Route = FitConnect.Services.Models.v1.Routes.Route;
 
 namespace FitConnect;
 
-public class Router : IRouter {
+internal class Router : IRouter {
     private readonly FitConnectEnvironment _environment;
     private readonly ILogger? _logger;
     private readonly IRouteService _routeService;
diff --git a/FitConnect/SecuritySpecification.cs b/FitConnect/SecuritySpecification.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d476074188e69935a77d371e82b91f020e95003f
--- /dev/null
+++ b/FitConnect/SecuritySpecification.cs
@@ -0,0 +1,18 @@
+using System.Security.Cryptography;
+using System.Text;
+
+namespace FitConnect;
+
+/// <summary>
+/// This class contains all security related methods that can be changed due to future
+/// security issues or decisions from the BSI.
+/// </summary>
+internal static class SecuritySpecification {
+    public const int MaxCallbackAge = 5;
+    
+    public static byte[] CalculateCallbackHmac(string callbackSecret, long timestamp, string body) {
+        return new HMACSHA512(Encoding.UTF8.GetBytes(callbackSecret))
+            .ComputeHash(Encoding.UTF8.GetBytes($"{timestamp}.{body}"));
+    }
+
+}
diff --git a/FitConnect/Sender.cs b/FitConnect/Sender.cs
index 6841c6abe34ca33bd6e932f0e304b94c143d3324..a140a1e438302b4f29b79917226a5ab7835e0c19 100644
--- a/FitConnect/Sender.cs
+++ b/FitConnect/Sender.cs
@@ -1,3 +1,4 @@
+using System.Security;
 using System.Text.RegularExpressions;
 using Autofac;
 using FitConnect.Encryption;
@@ -29,6 +30,9 @@ namespace FitConnect;
 /// </example>
 public class Sender : FitConnectClient, ISender, ISenderWithDestination,
     ISenderWithAttachments, ISenderWithData, ISenderWithService {
+    public string? PublicKey { get; set; }
+    public Submission? Submission { get; set; }
+
     public Sender(FitConnectEnvironment environment, string clientId, string clientSecret,
         ILogger? logger = null) : base(environment, clientId, clientSecret, logger) {
     }
@@ -38,10 +42,6 @@ public class Sender : FitConnectClient, ISender, ISenderWithDestination,
         container) {
     }
 
-    public Submission? Submission { get; set; }
-
-    public string? PublicKey { get; set; }
-
 
     public ISenderWithDestination FindDestinationId(string leiaKey, string? ags = null,
         string? ars = null,
@@ -181,8 +181,14 @@ public class Sender : FitConnectClient, ISender, ISenderWithDestination,
         return submission;
     }
 
-    private async Task<string> GetPublicKeyFromDestination(string destinationId) {
+    internal async Task<string> GetPublicKeyFromDestination(string destinationId) {
         var publicKey = await DestinationService.GetPublicKey(destinationId);
+
+        var keyIsValid = new CertificateHelper(Logger).ValidateCertificate(publicKey,
+            VerifiedKeysAreMandatory ? LogLevel.Error : LogLevel.Warning);
+        if (VerifiedKeysAreMandatory && !keyIsValid)
+            throw new SecurityException("Public key is not trusted");
+
         return publicKey;
     }
 
@@ -225,6 +231,20 @@ public class Sender : FitConnectClient, ISender, ISenderWithDestination,
         return JsonConvert.SerializeObject(metaData);
     }
 
+    /// <summary>
+    /// Finding Areas
+    /// </summary>
+    /// <param name="filter"></param>
+    /// <param name="totalCount"></param>
+    /// <param name="offset"></param>
+    /// <param name="limit"></param>
+    /// <returns></returns>
+    public IEnumerable<Area> GetAreas(string filter, out int totalCount, int offset = 0,
+        int limit = 100) {
+        var dto = RouteService.GetAreas(filter, offset, limit).Result;
+        totalCount = dto?.TotalCount ?? 0;
+        return dto?.Areas ?? new List<Area>();
+    }
 
     /// <summary>
     ///     Uploading the encrypted data to the server
diff --git a/FitConnect/Services/Interfaces/ISelfServicePortalService.cs b/FitConnect/Services/Interfaces/ISelfServicePortalService.cs
index dce0390c717dbc7e6df5c696f1a6f8c57f265c27..7b87c7804a264e92343ac2e828c46bb741d52acd 100644
--- a/FitConnect/Services/Interfaces/ISelfServicePortalService.cs
+++ b/FitConnect/Services/Interfaces/ISelfServicePortalService.cs
@@ -1,3 +1,4 @@
+using Jose;
 using Microsoft.IdentityModel.Tokens;
 
 namespace FitConnect.Services.Interfaces;
diff --git a/FitConnect/Services/Models/ServiceTypeDto.cs b/FitConnect/Services/Models/ServiceTypeDto.cs
index c34a7521674d279968d1b07a9c36c8421563055b..25591062ac054a093237cb3654ccc6ad84a7dd1b 100644
--- a/FitConnect/Services/Models/ServiceTypeDto.cs
+++ b/FitConnect/Services/Models/ServiceTypeDto.cs
@@ -12,3 +12,14 @@ public class ServiceTypeDto {
     [JsonProperty("identifier")]
     public string? Identifier { get; set; }
 }
+
+public class AcceptanceStatus {
+    [JsonProperty("metadata")]
+    public string? Metadata { get; set; }
+
+    [JsonProperty("data")]
+    public string? Data { get; set; }
+
+    [JsonProperty("attachments")]
+    public Dictionary<string, string> Attachments { get; set; } = new Dictionary<string, string>();
+}
diff --git a/FitConnect/Services/Models/v1/Api/Metadata.cs b/FitConnect/Services/Models/v1/Api/Metadata.cs
index c5ccaf433011c00cc3ca3068b80d95a09ac78c45..77fa78761a218643d7ada6cfa73899479c6af4e5 100644
--- a/FitConnect/Services/Models/v1/Api/Metadata.cs
+++ b/FitConnect/Services/Models/v1/Api/Metadata.cs
@@ -53,6 +53,8 @@ namespace FitConnect.Models.Api.Metadata
 
         [JsonProperty("replyChannel", NullValueHandling = NullValueHandling.Ignore)]
         public ReplyChannel ReplyChannel { get; set; }
+        
+        public override string ToString() => JsonConvert.SerializeObject(this);
     }
 
     /// <summary>
diff --git a/FitConnect/Services/Models/v1/Routes/Routes.cs b/FitConnect/Services/Models/v1/Routes/Routes.cs
index 375913cdd3a7f39f58c0108f8375e104bd279c8d..8719150b365692ec259ad3c0f311ffd8f6814f21 100644
--- a/FitConnect/Services/Models/v1/Routes/Routes.cs
+++ b/FitConnect/Services/Models/v1/Routes/Routes.cs
@@ -1,5 +1,4 @@
 // Root myDeserializedClass = JsonSerializer.Deserialize<Root>(myJsonResponse);
-
 #nullable disable
 using Newtonsoft.Json;
 
diff --git a/FitConnect/Services/Models/v1/Submission/SubmissionCreatedDto.cs b/FitConnect/Services/Models/v1/Submission/SubmissionCreatedDto.cs
index fa607ae2dfa44a67008a0052ee68f75abd6d6fb8..048c3490e83081d74952465691e80bf56f4b0026 100644
--- a/FitConnect/Services/Models/v1/Submission/SubmissionCreatedDto.cs
+++ b/FitConnect/Services/Models/v1/Submission/SubmissionCreatedDto.cs
@@ -4,11 +4,11 @@ namespace FitConnect.Services.Models.v1.Submission;
 
 public class SubmissionCreatedDto {
     [JsonProperty("destinationId")]
-    public string? DestinationId { get; set; }
+    public string DestinationId { get; set; } = null!;
 
     [JsonProperty("submissionId")]
-    public string? SubmissionId { get; set; }
+    public string SubmissionId { get; set; } = null!;
 
     [JsonProperty("caseId")]
-    public string? CaseId { get; set; }
+    public string CaseId { get; set; } = null!;
 }
diff --git a/FitConnect/Services/Models/v1/Submission/SubmissionDto.cs b/FitConnect/Services/Models/v1/Submission/SubmissionDto.cs
index 9a4f1aa1c17a3796cb435cc7ee5a6022597931de..1c0e3be45e4188ee8111f9434a463cf4491388c4 100644
--- a/FitConnect/Services/Models/v1/Submission/SubmissionDto.cs
+++ b/FitConnect/Services/Models/v1/Submission/SubmissionDto.cs
@@ -12,10 +12,10 @@ public class SubmissionDto {
 
 
     [JsonProperty("caseId")]
-    public string? CaseId { get; set; }
+    public string CaseId { get; set; } = null!;
 
     [JsonProperty("destinationId")]
-    public string? DestinationId { get; set; }
+    public string DestinationId { get; set; } = null!;
 
 
     [JsonProperty("encryptedData")]
@@ -31,5 +31,5 @@ public class SubmissionDto {
 
 
     [JsonProperty("submissionId")]
-    public string? SubmissionId { get; set; }
+    public string SubmissionId { get; set; } = null!;
 }
diff --git a/FitConnect/Services/Models/v1/Submission/SubmissionForPickupDto.cs b/FitConnect/Services/Models/v1/Submission/SubmissionForPickupDto.cs
index 7540c18ff8926a41e13d75ccfadd16e242339072..c1a7911aacd32b07f4bf7427993e173b18ad1523 100644
--- a/FitConnect/Services/Models/v1/Submission/SubmissionForPickupDto.cs
+++ b/FitConnect/Services/Models/v1/Submission/SubmissionForPickupDto.cs
@@ -10,5 +10,5 @@ public class SubmissionForPickupDto {
     public string? DestinationId { get; set; }
 
     [JsonProperty("submissionId")]
-    public string? SubmissionId { get; set; }
+    public string Id { get; set; } = null!;
 }
diff --git a/FitConnect/Services/OAuthService.cs b/FitConnect/Services/OAuthService.cs
index 19f915311ebb549601bb7df2013885e0de76cb90..1df17608f732d16abc599abca08c0b6ae965f30a 100644
--- a/FitConnect/Services/OAuthService.cs
+++ b/FitConnect/Services/OAuthService.cs
@@ -38,8 +38,6 @@ internal class OAuthService : RestCallService, IOAuthService {
     ///         https://portal.auth-testing.fit-connect.fitko.dev
     ///     </para>
     /// </summary>
-    /// <param name="clientId">Your client Id</param>
-    /// <param name="clientSecret">Your client Secret</param>
     /// <param name="scope">Scope if needed</param>
     /// <returns>The received token or null</returns>
     public async Task AuthenticateAsync(
diff --git a/FitConnect/Services/SelfServicePortalService.cs b/FitConnect/Services/SelfServicePortalService.cs
index 67269c1b30d9aa0dc9711a9a5e7a8e50a6511add..34d520ec72967f316f74891ad147bd277325c9f1 100644
--- a/FitConnect/Services/SelfServicePortalService.cs
+++ b/FitConnect/Services/SelfServicePortalService.cs
@@ -1,4 +1,5 @@
 using FitConnect.Services.Interfaces;
+using Jose;
 using Microsoft.Extensions.Logging;
 using Microsoft.IdentityModel.Tokens;
 
diff --git a/FitConnect/Services/SubmissionService.cs b/FitConnect/Services/SubmissionService.cs
index 49aa903b2d78ebcf0f312291ec387318363464e2..b937358b8a2811609152e5224eddfe87ce9aca70 100644
--- a/FitConnect/Services/SubmissionService.cs
+++ b/FitConnect/Services/SubmissionService.cs
@@ -152,7 +152,6 @@ internal class SubmissionService : RestCallService, ISubmissionService {
         if (events == null)
             return null;
 
-        // Download well known keys
         var valid = await ValidateSignature(events, destinationId);
         valid &= await ValidateSchema(events);
 
diff --git a/FitConnect/Subscriber.cs b/FitConnect/Subscriber.cs
index 7d08e9d4d306bfe4a441362d12e13f91e9779c8b..f957e3b36aaa3dacb266e8699d3f75ba7e3b3046 100644
--- a/FitConnect/Subscriber.cs
+++ b/FitConnect/Subscriber.cs
@@ -1,17 +1,21 @@
+using System.Net;
 using System.Reflection;
 using System.Security.Cryptography;
 using System.Text;
 using Autofac;
+using Autofac.Core.Activators.Reflection;
 using FitConnect.Encryption;
 using FitConnect.Interfaces.Subscriber;
 using FitConnect.Models;
 using FitConnect.Models.v1.Api;
+using FitConnect.Services.Models;
 using FitConnect.Services.Models.v1.Submission;
 using IdentityModel;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Logging;
 using Newtonsoft.Json;
 using NJsonSchema;
+using NJsonSchema.Annotations;
 using NJsonSchema.Validation;
 using Metadata = FitConnect.Models.Api.Metadata.Metadata;
 
@@ -23,6 +27,8 @@ namespace FitConnect;
 public class Subscriber : FitConnectClient,
     ISubscriber,
     ISubscriberWithSubmission {
+    public Submission? Submission { get; private set; }
+
     public Subscriber(FitConnectEnvironment environment,
         string clientId, string clientSecret,
         string privateKeyDecryption,
@@ -74,11 +80,8 @@ public class Subscriber : FitConnectClient,
     /// <param name="submissionId"></param>
     /// <param name="skipSchemaTest"></param>
     /// <returns></returns>
-    public ISubscriberWithSubmission RequestSubmission(string? submissionId,
+    public ISubscriberWithSubmission RequestSubmission(string submissionId,
         bool skipSchemaTest = false) {
-        if (submissionId == null)
-            throw new ArgumentNullException($"{nameof(submissionId)} has to be set");
-
         var submission = (Submission)SubmissionService.GetSubmission(submissionId);
         var (metaDataString, _, metaHash) = Encryption.Decrypt(submission.EncryptedMetadata!);
 
@@ -93,7 +96,6 @@ public class Subscriber : FitConnectClient,
 
         submission.Metadata = JsonConvert.DeserializeObject<Metadata>(metaDataString);
 
-
         if (submission.EncryptedData != null) {
             var (dataString, _, dataHash) = Encryption.Decrypt(submission.EncryptedData);
             submission.Data = dataString;
@@ -111,8 +113,6 @@ public class Subscriber : FitConnectClient,
         return this;
     }
 
-    public Submission? Submission { get; private set; }
-
 
     /// <summary>
     ///     Reading attachments for a submission.
@@ -129,7 +129,8 @@ public class Subscriber : FitConnectClient,
             var attachmentMeta =
                 Submission.Metadata.ContentStructure.Attachments.First(a => a.AttachmentId == id);
 
-            attachments.Add(new Attachment(attachmentMeta, content));
+            attachments.Add(new Attachment(attachmentMeta, content,
+                encryptedAttachment.Split('.').Last()));
         }
 
         Submission.Attachments = attachments;
@@ -153,11 +154,24 @@ public class Subscriber : FitConnectClient,
         CompleteSubmission(Submission!, status);
     }
 
+    public bool VerifyStatus(AcceptanceStatus acceptanceStatus) {
+        if (Submission == null)
+            throw new NullReferenceException("Submission is null");
+        var result = true;
+        result &= acceptanceStatus.Metadata == Submission.MetaAuthentication;
+        result &= acceptanceStatus.Data == Submission.DataAuthentication;
+        foreach (var attachment in Submission.Attachments) {
+            result &= acceptanceStatus.Attachments[attachment.Id] ==
+                      attachment.AttachmentAuthentication;
+        }
+
+        return result;
+    }
 
 
-    private void CompleteSubmission(SubmissionForPickupDto submission,
+    private void CompleteSubmission(Submission submission,
         FinishSubmissionStatus status, Problems[]? problems = null) {
-        if (submission.SubmissionId == null || submission.CaseId == null ||
+        if (submission.Id == null || submission.CaseId == null ||
             submission.DestinationId == null)
             throw new ArgumentException("Submission does not contain all required fields");
 
@@ -166,7 +180,7 @@ public class Subscriber : FitConnectClient,
 
         var token = status switch {
             FinishSubmissionStatus.Rejected =>
-                Encryption.CreateRejectSecurityEventToken(submission.SubmissionId,
+                Encryption.CreateRejectSecurityEventToken(submission.Id,
                     submission.CaseId,
                     submission.DestinationId, problems),
             FinishSubmissionStatus.Accepted => Encryption.CreateAcceptSecurityEventToken(
@@ -181,23 +195,22 @@ public class Subscriber : FitConnectClient,
 
     public static string VerifyCallback(string callbackSecret,
         long timestamp, string body) {
-        if (timestamp < DateTime.Now.AddMinutes(-5).ToEpochTime())
+        if (timestamp < DateTime.Now.AddMinutes(SecuritySpecification.MaxCallbackAge * -1)
+                .ToEpochTime())
             throw new ArgumentException("Request is too old");
-
-        var hmac = new HMACSHA512(Encoding.UTF8.GetBytes(callbackSecret))
-            .ComputeHash(Encoding.UTF8.GetBytes($"{timestamp}.{body}"));
-
-
+        var hmac = SecuritySpecification.CalculateCallbackHmac(callbackSecret, timestamp, body);
         return Convert.ToHexString(hmac).ToLower();
     }
 
+
     public static bool VerifyCallback(string callbackSecret, HttpRequest request) {
         if (!request.Headers.ContainsKey("callback-timestamp"))
             throw new ArgumentException("Missing callback-timestamp header");
 
         var timeStampString = request.Headers["callback-timestamp"].ToString();
-        if (!long.TryParse(timeStampString, out var timestamp))
+        if (!long.TryParse(timeStampString, out var timestamp)) {
             throw new ArgumentException("Invalid callback-timestamp header");
+        }
 
 
         var authentication = request.Headers["callback-authentication"];
diff --git a/IntegrationTests/CertificateValidation.cs b/IntegrationTests/CertificateValidation.cs
new file mode 100644
index 0000000000000000000000000000000000000000..7a26e50a8bff96bb44352117d7066bd4f2a44103
--- /dev/null
+++ b/IntegrationTests/CertificateValidation.cs
@@ -0,0 +1,183 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Security;
+using System.Security.Cryptography.X509Certificates;
+using Autofac;
+using FitConnect;
+using FitConnect.Encryption;
+using FitConnect.Models;
+using FluentAssertions;
+using Microsoft.Extensions.Logging;
+using Microsoft.IdentityModel.Tokens;
+using MockContainer;
+using Moq;
+using NUnit.Framework;
+
+namespace IntegrationTests;
+
+[TestFixture]
+public class CertificateValidation {
+    private MockSettings _settings = null!;
+    private ILogger _logger = null!;
+    private CertificateHelper _certificateHelper = null!;
+
+    [SetUp]
+    public void Setup() {
+        var container = Container.Create();
+        _settings = container.Resolve<MockSettings>();
+
+        _logger = LoggerFactory.Create(
+            builder => {
+                builder.AddConsole();
+                builder.SetMinimumLevel(LogLevel.Debug);
+            }).CreateLogger("E2E Test");
+
+
+        _certificateHelper = new CertificateHelper(_logger);
+    }
+
+    [Test]
+    [Ignore("No credentials for dev environment")]
+    public void CheckCertificateInEnvironment_Dev() {
+        var environment = FitConnectEnvironment.Develop;
+        var sender = Client.GetSender(environment, _settings.SenderClientId,
+            _settings.SenderClientSecret,
+            _logger);
+
+        var certificate = (sender as FitConnect.Sender)!
+            .GetPublicKeyFromDestination(_settings.DestinationId).Result;
+        new CertificateHelper(_logger).ValidateCertificate(JsonWebKey.Create(certificate),
+            LogLevel.Trace);
+    }
+
+    [Test]
+    public void CheckCertificateInEnvironment_Testing() {
+        var environment = FitConnectEnvironment.Testing;
+        var sender = Client.GetSender(environment, _settings.SenderClientId,
+            _settings.SenderClientSecret,
+            _logger);
+
+        var certificate = (sender as FitConnect.Sender)!
+            .GetPublicKeyFromDestination(_settings.DestinationId).Result;
+        new CertificateHelper(_logger).ValidateCertificate(JsonWebKey.Create(certificate),
+            LogLevel.Trace);
+    }
+
+
+    [Test]
+    [Ignore("No credentials for staging environment")]
+    public void CheckCertificateInEnvironment_Staging() {
+        var environment = FitConnectEnvironment.Staging;
+        var sender = Client.GetSender(environment, _settings.SenderClientId,
+            _settings.SenderClientSecret,
+            _logger);
+
+        Assert.Throws<AggregateException>(() => {
+            sender.WithDestination(_settings.DestinationId)
+                .WithServiceType("", _settings.LeikaKey)
+                .WithAttachments(new Attachment("Test.pdf", "Simple Test PDF"))
+                .Submit();
+        })!.InnerExceptions.Any(e => e.GetType() == typeof(SecurityException)).Should().BeTrue();
+    }
+
+    [Test]
+    [Ignore("No credentials for production environment")]
+    public void CheckCertificateInEnvironment_Production() {
+        var environment = FitConnectEnvironment.Production;
+        var sender = Client.GetSender(environment, _settings.SenderClientId,
+            _settings.SenderClientSecret,
+            _logger);
+
+        Assert.Throws<AggregateException>(() => {
+            sender.WithDestination(_settings.DestinationId)
+                .WithServiceType("", _settings.LeikaKey)
+                .WithAttachments(new Attachment("Test.pdf", "Simple Test PDF"))
+                .Submit();
+        })!.InnerExceptions.Any(e => e.GetType() == typeof(SecurityException)).Should().BeTrue();
+    }
+
+    [Test]
+    public void CheckPublicKeyEncryption() {
+        _certificateHelper.ValidateCertificate(new JsonWebKey(_settings.PublicKeyEncryption))
+            .Should().BeFalse();
+    }
+
+    [Test]
+    public void CheckPublicKeySignature() {
+        _certificateHelper
+            .ValidateCertificate(new JsonWebKey(_settings.PublicKeySignatureVerification))
+            .Should().BeFalse();
+    }
+
+    [Test]
+    public void CheckPrivateKeyDecryption() {
+        _certificateHelper.ValidateCertificate(new JsonWebKey(_settings.PrivateKeyDecryption))
+            .Should().BeTrue();
+    }
+
+    [Test]
+    public void CheckSetPublicKey() {
+        _certificateHelper.ValidateCertificate(new JsonWebKey(_settings.SetPublicKeys))
+            .Should().BeTrue();
+    }
+
+    [Test]
+    public void CheckPrivateKeySigning() {
+        _certificateHelper.ValidateCertificate(new JsonWebKey(_settings.PrivateKeySigning))
+            .Should().BeTrue();
+    }
+
+    [Test]
+    public void CheckPemFiles() {
+        var files = System.IO.Directory.GetFiles("./certificates");
+        var success = 0;
+        var failed = 0;
+        var failedCerts = new List<string>();
+
+        foreach (var fileName in files.Where(f => !f.EndsWith("root.pem"))) {
+            _logger.LogInformation("Checking file: {FileName}", fileName);
+
+
+            if (fileName.EndsWith(".pem")) {
+                var certificate = X509Certificate2.CreateFromPem(File.ReadAllText(fileName));
+                var valid = _certificateHelper.ValidateCertificate(certificate, out var states,
+                    null);
+                if (valid) {
+                    success++;
+                }
+                else {
+                    failed++;
+                    failedCerts.Add(fileName);
+                }
+            }
+
+            if (fileName.EndsWith(".json")) {
+                var shouldFail = !fileName.Contains("/valid");
+                var jwk = new JsonWebKey(File.ReadAllText(fileName));
+                var valid = _certificateHelper.ValidateCertificate(jwk,
+                    shouldFail ? LogLevel.Warning : LogLevel.Critical,
+                    Directory.GetFiles("./certificates/roots")
+                        .Select(file => new X509Certificate2(file)).ToArray());
+
+                if (shouldFail)
+                    valid = !valid;
+
+                if (valid) {
+                    success++;
+                }
+                else {
+                    failed++;
+                    failedCerts.Add(fileName);
+                }
+            }
+        }
+
+        _logger.LogWarning("Failed certificates: {Certs}",
+            failedCerts.Aggregate("\n", (a, b) => a + "\t - " + b + "\n"));
+        _logger.LogInformation("Success: {Success}, Failed: {Failed}", success, failed);
+        failed.Should().Be(0);
+    }
+}
diff --git a/IntegrationTests/IntegrationTests.csproj b/IntegrationTests/IntegrationTests.csproj
index 03b4ca3e126b1295f920a3e256c2a8224df1816d..9b8b7191f7b8e445d2b4267c954870582561c3d6 100644
--- a/IntegrationTests/IntegrationTests.csproj
+++ b/IntegrationTests/IntegrationTests.csproj
@@ -30,6 +30,111 @@
         <None Update="Test.pdf">
             <CopyToOutputDirectory>Always</CopyToOutputDirectory>
         </None>
+        <None Update="certificates\www-amazon-de.pem">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\www-amazon-de-zertifikatskette.pem">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\validEncJW_KeyUse.json">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\validEncJWK.json">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\validSigJWK.json">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\revokedEncJWK.json">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="temp\readme.md">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.21636.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.30244.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\root.pem">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.17478.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.29249.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.29267.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.29284.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.29302.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.29319.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.29336.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.29353.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.29370.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.29387.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\root\ca.26281.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\root\ca.26305.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\root\ca.30244.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\root\root.pem">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.1534.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.1553.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.1570.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.1587.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.1604.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.1622.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.1639.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.1656.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.1673.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.26281.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="certificates\roots\ca.26305.der">
+          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
     </ItemGroup>
 
 </Project>
diff --git a/IntegrationTests/Sender/ThreadTest.cs b/IntegrationTests/Sender/ThreadTest.cs
index c59372b206b870948ef118094a0edf47158f3e8e..2588b1db76c0418696901346514e9156392bab15 100644
--- a/IntegrationTests/Sender/ThreadTest.cs
+++ b/IntegrationTests/Sender/ThreadTest.cs
@@ -75,7 +75,7 @@ public class ThreadTest {
 
         foreach (var submission in submissions)
             subscriber
-                .RequestSubmission(submission.SubmissionId)
+                .RequestSubmission(submission.Id!)
                 .AcceptSubmission();
 
         submissions.Count.Should().Be(NumberOfThreads);
diff --git a/IntegrationTests/Subscriber/SubscriberTestHappyPath.cs b/IntegrationTests/Subscriber/SubscriberTestHappyPath.cs
index ee585fc6693fb33572091fb9dcfea7f372543d53..9255aed0061d7c5af65a71c18052bac6d2a418b9 100644
--- a/IntegrationTests/Subscriber/SubscriberTestHappyPath.cs
+++ b/IntegrationTests/Subscriber/SubscriberTestHappyPath.cs
@@ -42,7 +42,7 @@ public class SubscriberTestHappyPath : SubscriberTestBase {
         var submissions = Subscriber.GetAvailableSubmissions().ToList();
         submissions.Count().Should().BeGreaterThan(0);
         var i = 0;
-        foreach (var submissionId in submissions.Select(s => s.SubmissionId)) {
+        foreach (var submissionId in submissions.Select(s => s.Id!)) {
             // Act
             Console.WriteLine($"Getting submission {submissionId}");
             var dto = Subscriber.RequestSubmission(submissionId);
@@ -91,8 +91,8 @@ public class SubscriberTestHappyPath : SubscriberTestBase {
 
         foreach (var submission in submissions) {
             Console.WriteLine(
-                $"Getting submission {submission.SubmissionId} - case {submission.CaseId}");
-            var submissionId = submission.SubmissionId!;
+                $"Getting submission {submission.Id} - case {submission.CaseId}");
+            var submissionId = submission.Id!;
             if (!Directory.Exists($"./attachments/{submissionId}/"))
                 Directory.CreateDirectory($"./attachments/{submissionId}/");
 
diff --git a/IntegrationTests/temp/readme.md b/IntegrationTests/temp/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/MockContainer/MockContainer.cs b/MockContainer/MockContainer.cs
index 364259bc889d4e7690cd01a555011d7c58fe40dc..81f9b7f91b6a42029106470c8e250117e7e9453d 100644
--- a/MockContainer/MockContainer.cs
+++ b/MockContainer/MockContainer.cs
@@ -16,7 +16,7 @@ namespace MockContainer;
 public record MockSettings(string PrivateKeyDecryption, string PrivateKeySigning,
     string PublicKeyEncryption, string PublicKeySignatureVerification, string SenderClientId,
     string SenderClientSecret, string SubscriberClientId, string SubscriberClientSecret,
-    string DestinationId, string LeikaKey, string CallbackSecret);
+    string DestinationId, string LeikaKey, string CallbackSecret, string SetPublicKeys);
 
 public class TestFile {
     public byte[] Content;
@@ -63,6 +63,7 @@ public static class Container {
         var publicKeyEncryption = File.ReadAllText("./encryptionKeys/publicKey_encryption.json");
         var publicKeySignature =
             File.ReadAllText("./encryptionKeys/publicKey_signature_verification.json");
+        var setPublicKeys = File.ReadAllText("./encryptionKeys/set-public-keys.json");
 
         var credentials =
             JsonConvert.DeserializeObject<dynamic>(
@@ -81,7 +82,7 @@ public static class Container {
                 publicKeyEncryption, publicKeySignature,
                 senderClientId, senderClientSecret,
                 subscriberClientId, subscriberClientSecret,
-                destinationId, leikaKey, callbackSecret))
+                destinationId, leikaKey, callbackSecret, setPublicKeys))
             .As<MockSettings>();
         builder.Register(c => new KeySet {
             PrivateKeyDecryption = privateKeyDecryption,