diff --git a/src/main/java/xades4j/production/SignatureAlgorithms.java b/src/main/java/xades4j/production/SignatureAlgorithms.java index f0ffe3dd..7c23b0d8 100644 --- a/src/main/java/xades4j/production/SignatureAlgorithms.java +++ b/src/main/java/xades4j/production/SignatureAlgorithms.java @@ -23,6 +23,7 @@ import xades4j.algorithms.CanonicalXMLWithoutComments; import xades4j.algorithms.GenericAlgorithm; +import java.security.spec.AlgorithmParameterSpec; import java.util.HashMap; import java.util.Map; @@ -40,7 +41,7 @@ */ public final class SignatureAlgorithms { - private final Map keyAlgToSignatureAlg = new HashMap<>(); + private final Map keyAlgToSignatureAlg = new HashMap<>(); private Algorithm canonicalizationAlgorithmForSignature = new CanonicalXMLWithoutComments(); private Algorithm canonicalizationAlgorithmForTimeStampProperties = new CanonicalXMLWithoutComments(); private String digestAlgorithmForDataObjectReferences = MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA256; @@ -49,9 +50,9 @@ public final class SignatureAlgorithms public SignatureAlgorithms() { - keyAlgToSignatureAlg.put("DSA", new GenericAlgorithm(XMLSignature.ALGO_ID_SIGNATURE_DSA)); - keyAlgToSignatureAlg.put("RSA", new GenericAlgorithm(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256)); - keyAlgToSignatureAlg.put("EC", new GenericAlgorithm(XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA256)); + keyAlgToSignatureAlg.put("DSA", new SignatureMethodAlgorithm(XMLSignature.ALGO_ID_SIGNATURE_DSA)); + keyAlgToSignatureAlg.put("RSA", new SignatureMethodAlgorithm(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256)); + keyAlgToSignatureAlg.put("EC", new SignatureMethodAlgorithm(XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA256)); } /** @@ -63,11 +64,27 @@ public SignatureAlgorithms() */ public SignatureAlgorithms withSignatureAlgorithm(String keyAlgorithmName, String signatureAlgorithm) { - keyAlgToSignatureAlg.put(keyAlgorithmName, new GenericAlgorithm(signatureAlgorithm)); + keyAlgToSignatureAlg.put(keyAlgorithmName, new SignatureMethodAlgorithm(signatureAlgorithm)); return this; } - Algorithm getSignatureAlgorithm(String keyAlgorithmName) throws UnsupportedAlgorithmException + /** + * Set the signature algorithm and parameters to be used when the signing key has the given key algorithm. + * + * @param keyAlgorithmName the key's algorithm name as defined in JCA standard algorithm names + * @param signatureAlgorithm the signature algorithm + * @param parameters the signature algorithm parameters + * @return the current instance + */ + public SignatureAlgorithms withSignatureAlgorithm(String keyAlgorithmName, + String signatureAlgorithm, + AlgorithmParameterSpec parameters) + { + keyAlgToSignatureAlg.put(keyAlgorithmName, new SignatureMethodAlgorithm(signatureAlgorithm, parameters)); + return this; + } + + SignatureMethodAlgorithm getSignatureAlgorithm(String keyAlgorithmName) throws UnsupportedAlgorithmException { var algorithm = keyAlgToSignatureAlg.get(keyAlgorithmName); diff --git a/src/main/java/xades4j/production/SignatureMethodAlgorithm.java b/src/main/java/xades4j/production/SignatureMethodAlgorithm.java new file mode 100644 index 00000000..7f02ba1e --- /dev/null +++ b/src/main/java/xades4j/production/SignatureMethodAlgorithm.java @@ -0,0 +1,45 @@ +/* + * XAdES4j - A Java library for generation and verification of XAdES signatures. + * Copyright (C) 2024 Luis Goncalves. + * + * XAdES4j is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or any later version. + * + * XAdES4j is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with XAdES4j. If not, see . + */ + +package xades4j.production; + +import xades4j.algorithms.Algorithm; + +import javax.annotation.Nullable; +import java.security.spec.AlgorithmParameterSpec; + +final class SignatureMethodAlgorithm extends Algorithm +{ + private final AlgorithmParameterSpec parameters; + + SignatureMethodAlgorithm(String uri, @Nullable AlgorithmParameterSpec parameters) + { + super(uri); + this.parameters = parameters; + } + + SignatureMethodAlgorithm(String uri) + { + this(uri, null); + } + + @Nullable + AlgorithmParameterSpec getParameters() + { + return parameters; + } +} diff --git a/src/main/java/xades4j/production/SignerBES.java b/src/main/java/xades4j/production/SignerBES.java index a416ee13..b19cc28d 100644 --- a/src/main/java/xades4j/production/SignerBES.java +++ b/src/main/java/xades4j/production/SignerBES.java @@ -25,7 +25,6 @@ import org.apache.xml.security.transforms.Transforms; import org.apache.xml.security.utils.Constants; import org.apache.xml.security.utils.ElementProxy; -import org.apache.xml.security.utils.XMLUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -316,41 +315,40 @@ private String getDigestAlgUri() private XMLSignature createSignature(Document signatureDocument, String baseUri, String signingKeyAlgorithm) throws XAdES4jXMLSigException, UnsupportedAlgorithmException { - Algorithm signatureAlg = this.signatureAlgorithms.getSignatureAlgorithm(signingKeyAlgorithm); - Element signatureAlgElem = createElementForAlgorithm(signatureAlg, Constants._TAG_SIGNATUREMETHOD, signatureDocument); - + SignatureMethodAlgorithm signatureAlg = this.signatureAlgorithms.getSignatureAlgorithm(signingKeyAlgorithm); Algorithm canonAlg = this.signatureAlgorithms.getCanonicalizationAlgorithmForSignature(); - if (null == canonAlg) - { - throw new NullPointerException("Canonicalization algorithm not provided"); - } - Element canonAlgElem = createElementForAlgorithm(canonAlg, Constants._TAG_CANONICALIZATIONMETHOD, signatureDocument); + XMLSignature signature; try { - return new XMLSignature(signatureDocument, baseUri, signatureAlgElem, canonAlgElem); + signature = new XMLSignature( + signatureDocument, + baseUri, + signatureAlg.getUri(), + 0, + canonAlg.getUri(), + null, + signatureAlg.getParameters()); } catch (XMLSecurityException ex) { - // Following the code, doesn't seem to be thrown at all. throw new XAdES4jXMLSigException(ex.getMessage(), ex); } - } - - private Element createElementForAlgorithm(Algorithm algorithm, String elementName, Document signatureDocument) throws UnsupportedAlgorithmException - { - Element algorithmElem = XMLUtils.createElementInSignatureSpace(signatureDocument, elementName); - algorithmElem.setAttributeNS(null, Constants._ATT_ALGORITHM, algorithm.getUri()); - List algorithmParams = this.algorithmsParametersMarshaller.marshalParameters(algorithm, signatureDocument); - if (algorithmParams != null) + List canonAlgParams = this.algorithmsParametersMarshaller.marshalParameters(canonAlg, signatureDocument); + if (canonAlgParams != null) { - for (Node p : algorithmParams) + Element canonAlgElement = DOMHelper.getChildElementsByTagNameNS( + signature.getSignedInfo().getElement(), + Constants.SignatureSpecNS, Constants._TAG_CANONICALIZATIONMETHOD + ).get(0); + for (Node p : canonAlgParams) { - algorithmElem.appendChild(p); + canonAlgElement.appendChild(p); } } - return algorithmElem; + + return signature; } private static void digestManifests(Iterable manifests) throws XAdES4jXMLSigException diff --git a/src/main/java/xades4j/utils/DOMHelper.java b/src/main/java/xades4j/utils/DOMHelper.java index bb332500..0fedb863 100644 --- a/src/main/java/xades4j/utils/DOMHelper.java +++ b/src/main/java/xades4j/utils/DOMHelper.java @@ -16,10 +16,6 @@ */ package xades4j.utils; -import java.util.ArrayList; -import java.util.Collection; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; import org.apache.xml.security.utils.Constants; import org.apache.xml.security.utils.HelperNodeList; import org.w3c.dom.Document; @@ -27,6 +23,11 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.util.ArrayList; +import java.util.List; + /** * Utility methods for DOM nodes. * @author Luís @@ -163,10 +164,10 @@ public static Element getFirstDescendant( * @param localName element name * @return */ - public static Collection getChildElementsByTagNameNS(Element e, String namespaceURI, String localName) + public static List getChildElementsByTagNameNS(Element e, String namespaceURI, String localName) { Node node = e.getFirstChild(); - Collection elements = new ArrayList<>(); + List elements = new ArrayList<>(); while (node != null) { diff --git a/src/test/java/xades4j/production/OtherSignerTests.java b/src/test/java/xades4j/production/OtherSignerTests.java index 8d5139a9..5fe9102d 100644 --- a/src/test/java/xades4j/production/OtherSignerTests.java +++ b/src/test/java/xades4j/production/OtherSignerTests.java @@ -137,7 +137,7 @@ void testSignatureAlgorithms() throws Exception XadesSigner signer = new XadesCSigningProfile(keyingProviderNist, vdp) .withSignatureAlgorithms(new SignatureAlgorithms() .withSignatureAlgorithm("RSA", ALGO_ID_SIGNATURE_RSA_SHA512) - .withCanonicalizationAlgorithmForTimeStampProperties(new ExclusiveCanonicalXMLWithoutComments()) + .withCanonicalizationAlgorithmForTimeStampProperties(new ExclusiveCanonicalXMLWithoutComments("x", "y")) .withDigestAlgorithmForReferenceProperties(ALGO_ID_DIGEST_SHA512)) .with(DEFAULT_TEST_TSA) .newSigner(); @@ -157,6 +157,8 @@ void testSignatureAlgorithms() throws Exception var tsC14n = (Attr) xpath.evaluate("//xades:UnsignedSignatureProperties/xades:SignatureTimeStamp/ds:CanonicalizationMethod/@Algorithm", doc, XPathConstants.NODE); assertEquals(ALGO_ID_C14N_EXCL_OMIT_COMMENTS, tsC14n.getValue()); + var tsC14nParam = (Attr) xpath.evaluate("//xades:UnsignedSignatureProperties/xades:SignatureTimeStamp/ds:CanonicalizationMethod/exc-c14n:InclusiveNamespaces/@PrefixList", doc, XPathConstants.NODE); + assertEquals("x y", tsC14nParam.getValue()); var certReferenceDigest = (Attr) xpath.evaluate("//xades:UnsignedSignatureProperties/xades:CompleteCertificateRefs/xades:CertRefs/xades:Cert/xades:CertDigest/ds:DigestMethod/@Algorithm", doc, XPathConstants.NODE); assertEquals(ALGO_ID_DIGEST_SHA512, certReferenceDigest.getValue()); @@ -175,6 +177,8 @@ public String getNamespaceURI(String prefix) return QualifyingProperty.XADES_XMLNS; case "xades141": return QualifyingProperty.XADESV141_XMLNS; + case "exc-c14n": + return "http://www.w3.org/2001/10/xml-exc-c14n#"; } return null; } diff --git a/src/test/java/xades4j/production/SignerBESTest.java b/src/test/java/xades4j/production/SignerBESTest.java index d00922a0..9321ab5e 100644 --- a/src/test/java/xades4j/production/SignerBESTest.java +++ b/src/test/java/xades4j/production/SignerBESTest.java @@ -16,6 +16,7 @@ */ package xades4j.production; +import org.apache.xml.security.signature.XMLSignature; import org.apache.xml.security.utils.resolver.implementations.ResolverDirectHTTP; import org.apache.xml.security.utils.resolver.implementations.ResolverLocalFilesystem; import org.junit.jupiter.api.Test; @@ -36,6 +37,8 @@ import xades4j.properties.SigningCertificateProperty; import java.io.File; +import java.security.spec.MGF1ParameterSpec; +import java.security.spec.PSSParameterSpec; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -92,6 +95,21 @@ void testSignBESWithEllipticCurveKey() throws Exception outputDocument(doc, "document.signed.bes.ec.xml"); } + @Test + void testSignBESWithRsaPss() throws Exception + { + Document doc = getTestDocument(); + Element elemToSign = doc.getDocumentElement(); + + XadesSigner signer = new XadesBesSigningProfile(keyingProviderMy) + .withSignatureAlgorithms(new SignatureAlgorithms() + .withSignatureAlgorithm("RSA", XMLSignature.ALGO_ID_SIGNATURE_RSA_PSS, new PSSParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 64, 1))) + .newSigner(); + new Enveloped(signer).sign(elemToSign); + + outputDocument(doc, "document.signed.bes.rsa_pss.xml"); + } + @Test void testSignBESExternalRes() throws Exception { diff --git a/src/test/java/xades4j/verification/XadesVerifierImplTest.java b/src/test/java/xades4j/verification/XadesVerifierImplTest.java index c2938e67..c6071f6d 100644 --- a/src/test/java/xades4j/verification/XadesVerifierImplTest.java +++ b/src/test/java/xades4j/verification/XadesVerifierImplTest.java @@ -199,6 +199,13 @@ void testVerifyBESCounterSigCounterSig() throws Exception assertEquals(XAdESForm.BES, result.getSignatureForm()); } + @Test + void testVerifyBesSigAlgParams() throws Exception + { + var result = verifySignature("document.signed.bes.rsa_pss.xml"); + assertEquals(XAdESForm.BES, result.getSignatureForm()); + } + @Test void testVerifyBESEnrichT() throws Exception { diff --git a/src/test/xml/document.signed.bes.rsa_pss.xml b/src/test/xml/document.signed.bes.rsa_pss.xml new file mode 100644 index 00000000..a6de27be --- /dev/null +++ b/src/test/xml/document.signed.bes.rsa_pss.xml @@ -0,0 +1,77 @@ + + + Questions, unanswered + Steve and the flubberblubs + 1989 + + + What do you know? + Steve and the flubberblubs + 2006-10-17-08:31 + + + Who do you know? + Steve and the flubberblubs + 2006-10-17-08:35 + + + When do you know? + Steve and the flubberblubs + 2006-10-17-08:39 + + + Do you know? + Steve and the flubberblubs + 2006-10-17-08:44 + + + + + + + + + +64 +1 + + + + + + + +rD/g8soqKz8EiPUBhEWfcQacS0ta4ULHX3dKMEH6ZoQ= + + + + + + +GddpcMqEMdYowP4GlEdTiqQcp9Mym1Mz3o9CFSyCet8= + + + +UKoTfgDL22+mv7q9NmrtFyP55WBj8WNWTM+CXDrPk9aDxps5xS/wHv1X9k1bZK9O2nw4UAqBz42f +3h3o1or/JrDdI3w5gsY3+rFdzmUq2z0CC5I1yGkCsl9wepxJjFC9R+ODTd1rxzO0rFS+cCM8sOgr +7olgkXW4K+fViZ0KarY= + + + + +MIICbTCCAdqgAwIBAgIQpkK0uals+ItHxBlpJuypOTAJBgUrDgMCHQUAMD8xCzAJBgNVBAYTAlBU +MQ0wCwYDVQQKEwRJU0VMMQswCQYDVQQLEwJDQzEUMBIGA1UEAxMLSXRlcm1lZGlhdGUwHhcNMTAw +NjI1MTc1ODQ5WhcNMzkxMjMxMjM1OTU5WjBCMQswCQYDVQQGEwJQVDENMAsGA1UEChMESVNFTDEL +MAkGA1UECxMCQ0MxFzAVBgNVBAMTDkx1aXMgR29uY2FsdmVzMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCpP9acMX69Dbg9ciMLFc5dm1tlpTY9OTNZ/EaCYoGVhh/3+DFgyIbEer6SA24hpREm +AhNG9+Ca0AurDPPgb3aKWFY9pj1WcOctis0VsR0YvzqP+2IGFqKDCd7bXFvv2tI0dEvpdc0oO6PF +Q02xvJG0kxQf44XljOCjUBU43jkJawIDAQABo28wbTBrBgNVHQEEZDBigBBdbbL4pDKLT56PpOpA +/56toTwwOjELMAkGA1UEBhMCUFQxDTALBgNVBAoTBElTRUwxCzAJBgNVBAsTAkNDMQ8wDQYDVQQD +EwZUZXN0Q0GCEN00x9qe7SuWQvpLK0/oay8wCQYFKw4DAh0FAAOBgQBSma8g9dQjiQo4WUljRRuG +yMUVRyCqW/9oRz8+0EoLNR/AhrIlGqdNbqQ1BkncgNNdqMAus5VD34v/EhgrkgWN5fZajMpYsmcR +Ahu4PzJ6hggAlWWMy245JwIYuV0s1Oi39GVTxVNOBIX//AONZlGWO4S2Psb1mqdZ99b/MugsaA== + + + +2024-10-18T23:17:54.123+01:004btVb5gQ5cdcNhGpvDSWQZabPQrR9jf1x8e3YF9Ajss=cn=Itermediate,ou=CC,o=ISEL,c=PT-119284162484605703133798696662099777223vm5QpbblsWV7fCYXotPhNTeCt4nk8cLFuF36L5RJ4Ok=cn=TestCA,ou=CC,o=ISEL,c=PT-46248926895392336918291885380930606289AUaN+IdhKQqxIVmEOrFwq+Dn22ebTkXJqD3BoOP/x8E=cn=TestCA,ou=CC,o=ISEL,c=PT-99704378678639105802976522062798066869 + \ No newline at end of file diff --git a/src/test/xml/document.signed.bes.xml b/src/test/xml/document.signed.bes.xml index 0a649790..b2fb7023 100644 --- a/src/test/xml/document.signed.bes.xml +++ b/src/test/xml/document.signed.bes.xml @@ -26,33 +26,33 @@ - + - + rD/g8soqKz8EiPUBhEWfcQacS0ta4ULHX3dKMEH6ZoQ= - + -igFkxw7F/NXg/bThxx9rCrntkZZPR2SGONUstaKwMaw= +a2w44U/Ou7UF3CUxMLAV4TCjeOQe4shj5N4TefeDw0c= - + -EZVm+UYsf+GxgwMcnIUrNjErRa92b2SdLQmYt3ykzzg= +z2O98XkAnv7rvEBhUp8a3e482en9E3rWK5RZhxZCjfY= -mrrtoc49WjRilA7UL4wc0A+aOvMtKLOFEsDbyGu/7XpH53LdqZhHAelQHbGmp9lY96ylJZT+QVuW -U5DD490dQOFPmaHnJv14RE0Q1jib+/pLwFAANhw+Ljh6WNJ52p8eaqMjG625tFm49pEYHyII8AFx -rokxrUrhkeZgjMRZ6rE= +Mtcyoisi3w2QPHk3B9WYN1Zu2/BTHA7GKjIMr4Qph/QkCM67fr8YJVmTQGtrlJiU+XIhR4pFZS3t +NXc33/5sCu6kyF/lR1ee3r026M2ctnMieJE3qZACTe7DmqBqYRnSPVmNT7AZysCKPgtmEbrjYwii +i1LxQWW7ixKiezt7WJk= @@ -71,11 +71,11 @@ Ahu4PzJ6hggAlWWMy245JwIYuV0s1Oi39GVTxVNOBIX//AONZlGWO4S2Psb1mqdZ99b/MugsaA== -11223344556677889900 -2024-09-14T16:30:46.606+01:004btVb5gQ5cdcNhGpvDSWQZabPQrR9jf1x8e3YF9Ajss=cn=Itermediate,ou=CC,o=ISEL,c=PT-119284162484605703133798696662099777223vm5QpbblsWV7fCYXotPhNTeCt4nk8cLFuF36L5RJ4Ok=cn=TestCA,ou=CC,o=ISEL,c=PT-46248926895392336918291885380930606289AUaN+IdhKQqxIVmEOrFwq+Dn22ebTkXJqD3BoOP/x8E=cn=TestCA,ou=CC,o=ISEL,c=PT-99704378678639105802976522062798066869Isto é uma descrição do elemento raizhttp://elem.roothttp://doc1.txthttp://doc2.txttext/xmlMyEncodingIsto é uma descrição do elemento dentro do objecthttp://elem.in.objecthttp://doc3.txthttp://doc4.txttext/xmlMyEncodinghttp://uri.etsi.org/01903/v1.2.2#ProofOfCreationIndicates that the signer has created the signed data object (but not necessarily approved, nor sent it)#reference-6add820c-8f30-48d1-8f05-1fd7df183bd7#reference-232f940d-d826-450b-91f8-e310f6ebbd81MyQualifierhttp://uri.etsi.org/01903/v1.2.2#ProofOfApprovalIndicates that the signer has approved the content of the signed data objectMIIVSAYJKoZIhvcNAQcCoIIVOTCCFTUCAQMxDzANBglghkgBZQMEAgEFADCCAVUGCyqGSIb3DQEJ -EAEEoIIBRASCAUAwggE8AgEBBgsrBgEEAb9VA2QCADAxMA0GCWCGSAFlAwQCAQUABCDfSoevedd8 -6UeIGPQWRYzMqeBo1A8QCgy81pCsYBKrgwIFAWrh1v8YDzIwMjQwOTE0MTUzMDQ2WjAKAgEAgAIB -9IEBAQEB/wIGAZHxKHbroIGqpIGnMIGkMRcwFQYDVQQDDA5UU0ExIEFDQ1YgMjAxNjEQMA4GA1UE +11223344556677889900 +2024-10-18T22:32:38.806+01:004btVb5gQ5cdcNhGpvDSWQZabPQrR9jf1x8e3YF9Ajss=cn=Itermediate,ou=CC,o=ISEL,c=PT-119284162484605703133798696662099777223vm5QpbblsWV7fCYXotPhNTeCt4nk8cLFuF36L5RJ4Ok=cn=TestCA,ou=CC,o=ISEL,c=PT-46248926895392336918291885380930606289AUaN+IdhKQqxIVmEOrFwq+Dn22ebTkXJqD3BoOP/x8E=cn=TestCA,ou=CC,o=ISEL,c=PT-99704378678639105802976522062798066869Isto é uma descrição do elemento dentro do objecthttp://elem.in.objecthttp://doc3.txthttp://doc4.txttext/xmlMyEncodingIsto é uma descrição do elemento raizhttp://elem.roothttp://doc1.txthttp://doc2.txttext/xmlMyEncodinghttp://uri.etsi.org/01903/v1.2.2#ProofOfApprovalIndicates that the signer has approved the content of the signed data objecthttp://uri.etsi.org/01903/v1.2.2#ProofOfCreationIndicates that the signer has created the signed data object (but not necessarily approved, nor sent it)#reference-c626fd4d-9915-4111-bbc6-3d73452890ae#reference-34a27ff0-af0b-477a-ad04-d1313dc6dea2MyQualifierMIIVSAYJKoZIhvcNAQcCoIIVOTCCFTUCAQMxDzANBglghkgBZQMEAgEFADCCAVUGCyqGSIb3DQEJ +EAEEoIIBRASCAUAwggE8AgEBBgsrBgEEAb9VA2QCADAxMA0GCWCGSAFlAwQCAQUABCDp6+6QWaZS +jH95gnyyyqHhLccy+Hijt4Rcc/+YNmgZ8QIFAWyf7bEYDzIwMjQxMDE4MjEzMjM5WjAKAgEAgAIB +9IEBAQEB/wIGAZKhi/xMoIGqpIGnMIGkMRcwFQYDVQQDDA5UU0ExIEFDQ1YgMjAxNjEQMA4GA1UE CwwHUEtJQUNDVjFEMEIGA1UECgw7QWdlbmNpYSBkZSBUZWNub2xvZ8OtYSB5IENlcnRpZmljYWNp w7NuIEVsZWN0csOzbmljYSAtIEFDQ1YxETAPBgNVBAcMCFZhbGVuY2lhMREwDwYDVQQIDAhWYWxl bmNpYTELMAkGA1UEBhMCRVOhGzAZBggrBgEFBQcBAwQNMAswCQYHBACBl14BAaCCEDswgghgMIIG @@ -154,23 +154,23 @@ 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 @@ -249,18 +249,18 @@ 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 \ No newline at end of file