Skip to main content
Skip table of contents

Digitale ondertekening IMKL-pakket

Om het risico op verlies van integriteit van plannen te beperken, kan je optioneel een digitale handtekening plaatsen op je IMKL-bestanden. Dit is een mature en wijdverspreide state-of-the-art technologie. Het plaatsen van een digitale handtekening op het IMKL-bestand is optioneel.

  • Een digitale handtekening garandeert integriteit en authenticiteit van de IMKL-bestanden

  • IMKL-bestanden zijn zip-bestanden en worden als geheel ondertekend.

De aanwezigheid én controle van een digitale handtekening op het IMKL-bestand garandeert de non-repudiation (niet-weerlegbaarheid) van de KLB met betrekking tot de correct afgeleverde plannen.

Deze controle werkt end-to-end: van bij de KLB tot in het IMKL-archief. Ze is onafhankelijk van de onderliggende transporttechnologie (zoals HTTPS) en compenseert dus ook mogelijke – al dan niet nog onbekende – kwetsbaarheden in het transportprotocol volgens het defense-in-depth-principe.

Ontvangstbevestiging door Athumi

De aanwezigheid van een digitale handtekening levert op zich nog geen bewijs dat Athumi de doorgestuurde plannen effectief correct heeft ontvangen.

Om de ketting sluitend te maken, is een door Athumi digitaal ondertekende ontvangstbevestiging nodig. Daarom ondertekent Athumi het validatierapport van een digitaal ondertekend IMKL-bestand op zijn beurt digitaal.

Een positief validatierapport wordt zo een cryptografisch “ontvangstbewijs” (ook wel message disposition notification genoemd).

Dit ontvangstbewijs:

  • Bevat de datum en het exacte tijdstip van ontvangst (UTC)

  • Vormt een bijkomende garantie dat het IMKL-bestand niet achteraf werd vervangen

  • Biedt extra bescherming tegen antedateren

In feite wordt hiermee het principe van een aangetekend schrijven in digitale vorm toegepast.

Athumi neemt in het validatierapport op:

  • De cryptografische hash (SHA-256) van het IMKL-bestand

  • Het tijdstip (UTC) van ontvangst

  • Een digitale handtekening op het validatierapport

Controle door de KLB

Wil je als KLB cryptografische zekerheid over:

  • de integriteit van het transport, en

  • het opgeslagen IMKL-document,

dan kan je:

  • De hash vergelijken met de hash die je zelf berekende vóór verzending

  • De digitale handtekening van Athumi valideren

Heb je het IMKL-bestand zelf digitaal ondertekend? Dan hoef je in principe de hash niet meer te vergelijken. De ondertekende bevestiging dat Athumi jouw handtekening heeft gevalideerd, kan dan volstaan.

Digitale ondertekening van het IMKL-pakket

Digitale ondertekening is optioneel. De digitale ondertekening van het IMKL-pakket gebeurt volgens het RSA-algoritme en de SHA-256-hashfunctie. Cfr http://en.wikipedia.org/wiki/RSA_(cryptosystem) .

Een digitaal ondertekend IMKL-pakket bestaat uit een zip-bestand met daarin:

  • Eén tekstbestand met de signature (base64-gecodeerde geëncrypteerde hash) (*.txt)

  • Eén X.509-certificaat met de publieke sleutel van het certificaat dat gebruikt werd om de hash te encrypteren (*.cer).

  • Eén IMKL-pakket (*.zip)

De naam van de bestanden (met uitzondering van de bestandsextensie) is vrij te kiezen.

Voorbeeld van een digitaal ondertekend IMKL-pakket:

signedimklfile-20240418-153611.png

Controle van het certificaat

Athumi controleert de geldigheid van het gebruikte certificaat.

Daarvoor bezorg je als KLB de publieke sleutels van het root-certificaat en van eventuele tussenliggende certificaten aan Athumi. Dat kan via e-mail naar klip@athumi.eu.

  • Self-signed certificaten zijn niet toegelaten.

Daarnaast vergelijkt Athumi het subject van het gebruikte certificaat met het subject dat je invult op de profielpagina.

  • Ontbreekt het subject op de profielpagina?

  • Of wijkt het subject af van het subject in het IMKL-pakket?

Dan zal het IMKL-pakket niet valideren.

profile-subject-signing-certificate-20240418-153958.png

Je vindt het subject van het certificaat in de gedetailleerde eigenschappen van het certificaat.

Voorbeeld code (C#)

Voor het berekenen van de base64-gecodeerde gesignde SHA-256-hash van een IMKL-pakket. Deze waarde komt in het *.txt bestand:

CODE
public class ImklSigner
{
    public string Sign(byte[] zip, X509Certificate2 cert)
    {
        using (var rsa = (RSACryptoServiceProvider)cert.PrivateKey)
        {
            return Convert.ToBase64String(rsa.SignData(zip, "SHA256"));
        }
    }
}

Digitale ondertekening van het validatierapport

De validatierapporten van IMKL-pakketten worden door Athumi digitaal ondertekend.

Zo’n validatierapport bevat:

  • Het tijdstip van ontvangst (UTC)

  • De cryptografische hash van het opgeladen IMKL-pakket

Een KLB kan een validatierapport opvragen via volgende URI: ws/klip/v2/Imkl/Report/MapRequest/{mapRequestId}/UnaZone/{unaZoneId}

Ondertekening van XML-rapporten

Een validatierapport in XML wordt digitaal ondertekend volgens het XML-DSig-principe. Cfr. http://en.wikipedia.org/wiki/XML_Signature.

Er bestaat momenteel nog geen internationale standaard voor het digitaal ondertekenen van JSON-berichten. Daarom heeft Athumi hiervoor een eigen formaat gedefinieerd.

Voorbeeld van een digitaal ondertekend validatierapport in XML:

XML
<ImklReport xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://api.agiv.be/ws/klip/v1">
    <DateReceived>2015-10-26T08:43:20.107Z</DateReceived>
    <SignatureValue>XtOnuzGYsVmqUFmXbRg3zKXs6/6lkivNERBNfEB3MrMi0iUE97xB+KwDcA1DaCmV7f9XfOWQkyBVKyyYuf2BhHoe2y8gNW8rQlr42VpuCBlnHZ/oYDWvD/rbkYbosc3sPVikh83a9qhy+BaNuRDB53TmK1C4y6kCaoVNe1Ip0qjn2tUY5TvuzePoif91qxT+VLaVxS7TAuwT97bf0iljHi6naVCt22KPCD/VfQjM5Z2lNCFaLAWYpXz6Xgwg6xnduhQCjOW11H2mNgvt1Ou/gFm1b/cw7VvCDNkIIwwRZ+tRTCDiJU1Sbjh+jpKUOdsJI9h1Ig+E3eDv+9ZloZbe8A==</SignatureValue>
    <CertificateThumbprint>2081c1d735b2f224d61c13f7e29e3b056afa2529</CertificateThumbprint>
    <MapRequestId>1a540b0f-8536-47d2-90af-28333be7ab66</MapRequestId>
    <ZoneId>e444932b-4a04-4aed-bdf7-2e1f70d47cab</ZoneId>
    <Status>https://klip.vlaanderen.be/api/cl/klip/v2/ImklStatus/datavalid</Status>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
            <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
            <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
            <Reference URI="">
                <Transforms>
                    <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                </Transforms>
                <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
                <DigestValue>qVmokZ+v9HWvkti/NABuQpwsIj3nf1mNsc9ymCDRjjc=</DigestValue>
            </Reference>
        </SignedInfo>
        <SignatureValue>YMH3hEPHL8sH1sgyjsjmxeCGOJhJW0kyNxAFyK8kOQSS9WBeDi7Oa7GNgY2dEGhaWf3ijrYJzKNzOTki+0CCbc2OHNSSmlRmcTJrlgmjqUzjhY6+pFJt3gTEh1d+fKwVW3tv0bTNKb4eMg1WO3XGf/hTEh6pqvkqaoIjAoput/GDts69iGvhuTI6cWC2rmJlJOMkYTU2rEPGLwuypRAomobmgp1TrS1vRvYG9Q/sRIGLJDmAegyGgmxEfjDRd0DDvRKCQuXtcRZNvGyZ5S3wyvdC3yR/5RAIFsk5XW9fo9/NkDSgHyK/EKA99oRZidXwcTxZfD8ZycFhquSPlLKT4Q==</SignatureValue>
        <KeyInfo>
            <X509Data>
                <X509Certificate>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</X509Certificate>
            </X509Data>
        </KeyInfo>
    </Signature>
</ImklReport>

Voorbeeld van een digitaal ondertekend validatierapport in JSON:

JSON
{
    "DateReceived" : "2015-10-26T08:43:20.107Z",
    "SignatureValue" : "XtOnuzGYsVmqUFmXbRg3zKXs6/6lkivNERBNfEB3MrMi0iUE97xB+KwDcA1DaCmV7f9XfOWQkyBVKyyYuf2BhHoe2y8gNW8rQlr42VpuCBlnHZ/oYDWvD/rbkYbosc3sPVikh83a9qhy+BaNuRDB53TmK1C4y6kCaoVNe1Ip0qjn2tUY5TvuzePoif91qxT+VLaVxS7TAuwT97bf0iljHi6naVCt22KPCD/VfQjM5Z2lNCFaLAWYpXz6Xgwg6xnduhQCjOW11H2mNgvt1Ou/gFm1b/cw7VvCDNkIIwwRZ+tRTCDiJU1Sbjh+jpKUOdsJI9h1Ig+E3eDv+9ZloZbe8A==",
    "CertificateThumbprint" : "2081c1d735b2f224d61c13f7e29e3b056afa2529",
    "MapRequestId" : "1a540b0f-8536-47d2-90af-28333be7ab66",
    "ZoneId" : "e444932b-4a04-4aed-bdf7-2e1f70d47cab",
    "Status" : "https://klip.vlaanderen.be/api/cl/klip/v2/ImklStatus/datavalid",
    "Signature" : {
        "SignedInfo" : {
            "SignatureMethod" : {
                "Algorithm" : "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
            }
        },
        "SignatureValue" : "DbaSpEWOoestxKrZXcyX1r8WRd/yUnBy3ltPiwcJbAZT9Xt9abHlI/MKha8dCTJs7mATfiEED8LpIbAjGoRqtyLE5ASAGjR6bJKCGqkgmlD1B7A6tPJ+xkP3gt/doASjAFdKeEpFNTAFXdL5ZTn6rzmRQWW3Xmt0ZDeECVGUQnge7p9SRiOM/2yieRp3NJCSfG/JzhYv5JorY0Tgoaowfa5Hqsyw+8Nv+q7F7wwzdatovELZwfdOm9yuU9FUj8hoA5qevKAt8dP5wtmWoNjEXYwQgHw+/BXDcGlOJHnG9QctwtqEw+j+lsbLXWy3MoWQ0HP5iH6qlN2OgqwzH/7brw==",
        "KeyInfo" : {
            "X509Data" : {
                "X509Certificate" : "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"
            }
        }
    }
}

Voorbeeld code (C#) voor het verifiëren van een digitaal ondertekend XML-bericht:

CPP
namespace Gisvl.Klipdf.ImklReportSignatureVerifier
{
    using System;
    using System.Linq;
    using System.Security.Cryptography;
    using System.Security.Cryptography.X509Certificates;
    using System.Security.Cryptography.Xml;
    using System.Xml;
    using System.Xml.Linq;
    public class XmlSignatureVerifier
    {
        public bool IsValid(string xml)
        {
            CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
            var xmlDocument = new XmlDocument();
            xmlDocument.PreserveWhitespace = false;
            xmlDocument.LoadXml(xml);
            var signedXml = new SignedXml(xmlDocument);
            var nodeList = xmlDocument.GetElementsByTagName("Signature");
            
            // assert that there is only one Signature element
            if (nodeList.Count != 1)
            {
                return false;
            }
            
            // Load the signature node.
            var element = (XmlElement)nodeList[0];
            signedXml.LoadXml(element);
            
            // get the public key
            var xelement = XElement.Parse(element.OuterXml);
            XNamespace ns = "http://www.w3.org/2000/09/xmldsig#";
            var certificate = xelement.Descendants(ns + "X509Certificate").Single();
            var binaryCertData = Convert.FromBase64String(certificate.Value);
            var cert = new X509Certificate2(binaryCertData);
            // assert that the reference uri is an empty string
            var uri = xelement.Descendants(ns + "Reference").Single().Attribute("URI");
            if (!string.IsNullOrEmpty(uri.Value))
            {
                return false;
            }
            
            // assert that the certificate is not expired
            var notBefore = cert.NotBefore;
            var notAfter = cert.NotAfter;
            if (DateTime.Now < notBefore || DateTime.Now > notAfter)
            {
                return false;
            }
            // assert that the certificate is an Informatie Vlaanderen certificate (beta: 2081C1D735B2F224D61C13F7E29E3B056AFA2529 ; production: D5D39A8C82FD1D68B5D86FBE94ED96AC8F8F9953)
            if (cert.Thumbprint != "2081C1D735B2F224D61C13F7E29E3B056AFA2529")
            {
                return false;
            }
            
            // Verify the signature and if certificate is valid and not revoked and return the result
            return signedXml.CheckSignature(cert, true);
        }
    }
}
                                 
namespace Gisvl.Klipdf.ImklReportSignatureVerifier
{
    using System;
    using System.Security.Cryptography;
    public sealed class RSAPKCS1SHA256SignatureDescription : SignatureDescription
    {
        public RSAPKCS1SHA256SignatureDescription()
        {
            KeyAlgorithm = typeof(RSACryptoServiceProvider).FullName;
            DigestAlgorithm = typeof(SHA256Managed).FullName;
            FormatterAlgorithm = typeof(RSAPKCS1SignatureFormatter).FullName;
            DeformatterAlgorithm = typeof(RSAPKCS1SignatureDeformatter).FullName;
        }
        public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            var deformatter = new RSAPKCS1SignatureDeformatter(key);
            deformatter.SetHashAlgorithm("SHA256");
            return deformatter;
        }
        public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            var formatter = new RSAPKCS1SignatureFormatter(key);
            formatter.SetHashAlgorithm("SHA256");
            return formatter;
        }
    }
}
                            
namespace Gisvl.Klipdf.ImklReportSignatureVerifier
{
    using NUnit.Framework;
    public class XmlSignatureVerifierTest
    {
        [Test]
        public void Test()
        {
            const string xml = "<imklreport xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://api.agiv.be/ws/klip/v1\"><datereceived>2015-10-26T08:43:20.107Z</datereceived><signaturevalue>XtOnuzGYsVmqUFmXbRg3zKXs6/6lkivNERBNfEB3MrMi0iUE97xB+KwDcA1DaCmV7f9XfOWQkyBVKyyYuf2BhHoe2y8gNW8rQlr42VpuCBlnHZ/oYDWvD/rbkYbosc3sPVikh83a9qhy+BaNuRDB53TmK1C4y6kCaoVNe1Ip0qjn2tUY5TvuzePoif91qxT+VLaVxS7TAuwT97bf0iljHi6naVCt22KPCD/VfQjM5Z2lNCFaLAWYpXz6Xgwg6xnduhQCjOW11H2mNgvt1Ou/gFm1b/cw7VvCDNkIIwwRZ+tRTCDiJU1Sbjh+jpKUOdsJI9h1Ig+E3eDv+9ZloZbe8A==</signaturevalue><certificatethumbprint>2081c1d735b2f224d61c13f7e29e3b056afa2529</certificatethumbprint><maprequestid>1a540b0f-8536-47d2-90af-28333be7ab66</maprequestid><zoneid>e444932b-4a04-4aed-bdf7-2e1f70d47cab</zoneid><status>https://klip.vlaanderen.be/api/cl/klip/v2/ImklStatus/datavalid</status><signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><signedinfo><canonicalizationmethod algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\" /><signaturemethod algorithm=\"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\" /><reference uri=\"\"><transforms><transform algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\" /></transforms><digestmethod algorithm=\"http://www.w3.org/2001/04/xmlenc#sha256\" /><digestvalue>qVmokZ+v9HWvkti/NABuQpwsIj3nf1mNsc9ymCDRjjc=</digestvalue></reference></signedinfo><signaturevalue>YMH3hEPHL8sH1sgyjsjmxeCGOJhJW0kyNxAFyK8kOQSS9WBeDi7Oa7GNgY2dEGhaWf3ijrYJzKNzOTki+0CCbc2OHNSSmlRmcTJrlgmjqUzjhY6+pFJt3gTEh1d+fKwVW3tv0bTNKb4eMg1WO3XGf/hTEh6pqvkqaoIjAoput/GDts69iGvhuTI6cWC2rmJlJOMkYTU2rEPGLwuypRAomobmgp1TrS1vRvYG9Q/sRIGLJDmAegyGgmxEfjDRd0DDvRKCQuXtcRZNvGyZ5S3wyvdC3yR/5RAIFsk5XW9fo9/NkDSgHyK/EKA99oRZidXwcTxZfD8ZycFhquSPlLKT4Q==</signaturevalue><keyinfo><x509data><x509certificate>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</x509certificate></x509data></keyinfo></signature></imklreport>";
            var verifier = new XmlSignatureVerifier();
            Assert.IsTrue(verifier.IsValid(xml));
        }
    }
}

Voorbeeld code (C#) voor het verifiëren van een digitaal ondertekend JSON-bericht:

CPP
namespace Gisvl.Klipdf.ImklReportSignatureVerifier
{
    using Newtonsoft.Json.Linq;
    using System;
    using System.Security.Cryptography;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
    public class JsonSignatureVerifier
    {
        public bool IsValid(string json)
        {
            var jObject = JObject.Parse(json);
            // get the public key
            var certToken = jObject.SelectToken("Signature.KeyInfo.X509Data.X509Certificate");
            var binaryCertData = Convert.FromBase64String(certToken.Value<string>());
            var cert = new X509Certificate2(binaryCertData);
            // assert that the certificate is not expired
            var notBefore = cert.NotBefore;
            var notAfter = cert.NotAfter;
            if (DateTime.Now < notBefore || DateTime.Now > notAfter)
            {
                return false;
            }
            // assert that the certificate is an AIV certificate (beta: 2081C1D735B2F224D61C13F7E29E3B056AFA2529 ; production: D5D39A8C82FD1D68B5D86FBE94ED96AC8F8F9953)
            if (cert.Thumbprint != "2081C1D735B2F224D61C13F7E29E3B056AFA2529")
            {
                return false;
            }
            // verify if the certificate is valid and not revoked
            if (!cert.Verify())
            {
                return false;
            }
            // get the signature
            var signatureToken = jObject.SelectToken("Signature.SignatureValue");
            var signature = signatureToken.Value<string>();
            // remove the signature element
            jObject.Remove("Signature");
            var strippedjson = jObject.ToString(Newtonsoft.Json.Formatting.None);
            // verify
            using (var rsa = (RSACryptoServiceProvider)cert.PublicKey.Key)
            {
                return rsa.VerifyData(Encoding.UTF8.GetBytes(strippedjson), "SHA256", Convert.FromBase64String(signature));
            }
        }
    }
}
namespace Gisvl.Klipdf.ImklReportSignatureVerifier
{
    using NUnit.Framework;
    public class JsonSignatureVerifierTest
    {
        [Test]
        public void Test()
        {
            const string json = "{\"DateReceived\":\"2015-10-26T08:43:20.107Z\",\"SignatureValue\":\"XtOnuzGYsVmqUFmXbRg3zKXs6/6lkivNERBNfEB3MrMi0iUE97xB+KwDcA1DaCmV7f9XfOWQkyBVKyyYuf2BhHoe2y8gNW8rQlr42VpuCBlnHZ/oYDWvD/rbkYbosc3sPVikh83a9qhy+BaNuRDB53TmK1C4y6kCaoVNe1Ip0qjn2tUY5TvuzePoif91qxT+VLaVxS7TAuwT97bf0iljHi6naVCt22KPCD/VfQjM5Z2lNCFaLAWYpXz6Xgwg6xnduhQCjOW11H2mNgvt1Ou/gFm1b/cw7VvCDNkIIwwRZ+tRTCDiJU1Sbjh+jpKUOdsJI9h1Ig+E3eDv+9ZloZbe8A==\",\"CertificateThumbprint\":\"2081c1d735b2f224d61c13f7e29e3b056afa2529\",\"MapRequestId\":\"1a540b0f-8536-47d2-90af-28333be7ab66\",\"ZoneId\":\"e444932b-4a04-4aed-bdf7-2e1f70d47cab\",\"Status\":\"https://klip.vlaanderen.be/api/cl/klip/v2/ImklStatus/datavalid\",\"Signature\":{\"SignedInfo\":{\"SignatureMethod\":{\"Algorithm\":\"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\"}},\"SignatureValue\":\"DbaSpEWOoestxKrZXcyX1r8WRd/yUnBy3ltPiwcJbAZT9Xt9abHlI/MKha8dCTJs7mATfiEED8LpIbAjGoRqtyLE5ASAGjR6bJKCGqkgmlD1B7A6tPJ+xkP3gt/doASjAFdKeEpFNTAFXdL5ZTn6rzmRQWW3Xmt0ZDeECVGUQnge7p9SRiOM/2yieRp3NJCSfG/JzhYv5JorY0Tgoaowfa5Hqsyw+8Nv+q7F7wwzdatovELZwfdOm9yuU9FUj8hoA5qevKAt8dP5wtmWoNjEXYwQgHw+/BXDcGlOJHnG9QctwtqEw+j+lsbLXWy3MoWQ0HP5iH6qlN2OgqwzH/7brw==\",\"KeyInfo\":{\"X509Data\":{\"X509Certificate\":\"MIIF+TCCA+GgAwIBAgIOAQAAAAABSR5mwERBAI0wDQYJKoZIhvcNAQELBQAwNjELMAkGA1UEBhMCQkUxFjAUBgNVBAMTDUdvdmVybm1lbnQgQ0ExDzANBgNVBAUTBjIwMTQwMjAeFw0xNDEwMTcxMzU4MTBaFw0yMDAxMTcxMzU4MTBaMIGkMSIwIAYDVQQDDBlrbGlwLnNpZ25pbmcuYWdpdi5iZS9iZXRhMQswCQYDVQQGEwJCRTEfMB0GCSqGSIb3DQEJARYQc2VjdXJpdHlAYWdpdi5iZTENMAsGA1UEBwwER2VudDEYMBYGA1UECAwPT29zdC1WbGFhbmRlcmVuMRIwEAYDVQQLDAlJVC1EaWVuc3QxEzARBgNVBAoMCjA4ODE3NDY1MjkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMR4iZqa/ba/ljL5hYdDgh2d682yEVy1zb2WP0MAkM5bTWvnmNagtT5B3ZWsayyCmmfL6vhbQ/Koa6rP2O+3K83Ng3uCb389HdAaspPXM6QukLhbCuF73HEqMBFs5wGBpzwcTC4XDKpSLi9CD3S96sLknXj0r8RbMw3WxZPGuOhhZoQb9WUs9aNYXV3oxBY3QvEdmajEMgmeEb/8w4WMt2fN5JBRCCeovhL5NbmmkfKCfQsx7uocXA+qvD7J5P8Vp+NSOz3T3HSv3XF+znpk5fe4UrqJMf06k63v4hPQ24/SAvmI74egZshy5ye1rDL04Z1X+0o2XcJLtnBdQ8rx5jAgMBAAGjggGUMIIBkDAfBgNVHSMEGDAWgBSO6Dkuol6Mul/B7QIppc9Aw7mbujBwBggrBgEFBQcBAQRkMGIwNgYIKwYBBQUHMAKGKmh0dHA6Ly9jZXJ0cy5wa2kuYmVsZ2l1bS5iZS9iZWxnaXVtcnM0LmNydDAoBggrBgEFBQcwAYYcaHR0cDovL29jc3AucGtpLmJlbGdpdW0uYmUvMjAJBgNVHRMEAjAAMEQGA1UdIAQ9MDswOQYHYDgMAQEDAzAuMCwGCCsGAQUFBwIBFiBodHRwOi8vcmVwb3NpdG9yeS5wa2kuYmVsZ2l1bS5iZTA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLnBraS5iZWxnaXVtLmJlL2dvdmVybm1lbnQyMDE0MDIuY3JsMA4GA1UdDwEB/wQEAwIE8DARBglghkgBhvhCAQEEBAMCBLAwHQYDVR0OBBYEFAJAEZ2JWVM1qboizHpo7jAqzyuEMCcGA1UdJQQgMB4GCCsGAQUFBwMCBggrBgEFBQcDAwYIKwYBBQUHAwQwDQYJKoZIhvcNAQELBQADggIBAB5aQzbgSTIH7zoPOI/JTNhSIXj7UHWs1dmow2AXgtoPToJR4/qq++/mMoHFM0R79xPrQuWrnkMKcuhsemrc21XzmSvA1FYYcCjrXHrSnffesCF1yb2g/2JiPlOYjWYeNCD279brnL0vEoMFXwGyGMvTh0lKiB3uO1R0MLhmdMkavi6iQ2XDTO/RC1lgC4x8gcPituldM7mrbxwNbnYV3VP063AmeA9vgwrgqbhbTLrE5rVZ1PbS0EBtoiTLIhUSLIsY+CQf2MNMHR00gwnv8cUSErO4te5oJEWjKiGd0aiSW6wbbVJSzn97kafmk/lB7/ZiEKyl0xYHJ+8cegSRxPkQN1VvHIj8WhO5zLpMxRh0xfW5XIo0yPLCMBz1PDMlWQOk7LHE81DqpzJgwifuHSGlnuLNwmSmYr6ntBA9Y/9gKkBHtmrLa5c3UYJ3QdGEE3aXQ+WKwZT6B+YkPAKH+LPH0MSeI6Gu7YeSHbe3Znczl2e88unlWt4uy/kGURaG5bPwlv3g4lU2R62kSK/EyrNG3wSItfODEocgjJwoP62RydOhqrugRMDulPVREyXWVyWWQng3V0vxbeXyeeOfonXzFaDSQh7Yx1H+44FukCbhtDH/fqYuy52QprllinNaSTjC7aA0CKKWmDaCOdeaQZ/TBCwJJt/XCJoTfDUVgOdU\"}}}}";
            var verifier = new JsonSignatureVerifier();
            Assert.IsTrue(verifier.IsValid(json));
        }
    }
} 
JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.