From 2b9a4f35e2e50fca4304107b5033b6216af0124d Mon Sep 17 00:00:00 2001 From: Bartosz Gardziejewski Date: Tue, 12 Jan 2021 10:33:18 +0100 Subject: Add support for signature in PCKS7 format. Signed-off-by: Bartosz Gardziejewski Change-Id: Ic98d1b9c93c11c484c86338588922c2f347b7c02 Issue-ID: VNFSDK-714 --- .../r130206/CsarSourceSecurityValidator.java | 2 +- .../org/onap/cvc/csar/cc/sol004/r130206/Error.java | 4 +- .../cvc/csar/security/CmsSignatureDataFactory.java | 25 +--- .../onap/cvc/csar/security/SignatureFactory.java | 60 ++++++++ .../VTPValidateCSARR130206IntegrationTest.java | 114 +++++++++++++++ .../cvc/csar/security/SignatureFactoryTest.java | 159 +++++++++++++++++++++ .../functional/PnfValidationFunctionalTest.java | 16 ++- ...d-with-signature-of-individual-artifact-p7.csar | Bin 0 -> 28210 bytes ...th-signature-of-individual-artifact-p7-DER.csar | Bin 0 -> 28105 bytes ...d-with-signature-of-individual-artifact-p7.csar | Bin 0 -> 28274 bytes ...ndividual-p7-signature-common-cert-invalid.csar | Bin 0 -> 26695 bytes ...-individual-p7-signature-common-cert-valid.csar | Bin 0 -> 26707 bytes ...ert-in-tosca-multiple-individual-signature.csar | Bin 10824 -> 12975 bytes .../signature/testEncodedSignature.sig.p7c | Bin 0 -> 1515 bytes .../security/signature/testSignature.sig.cms | 34 +++++ .../security/signature/testSignature.sig.p7b | 34 +++++ 16 files changed, 421 insertions(+), 27 deletions(-) create mode 100644 csarvalidation/src/main/java/org/onap/cvc/csar/security/SignatureFactory.java create mode 100644 csarvalidation/src/test/java/org/onap/cvc/csar/security/SignatureFactoryTest.java create mode 100644 csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-invalid-with-signature-of-individual-artifact-p7.csar create mode 100644 csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-valid-with-signature-of-individual-artifact-p7-DER.csar create mode 100644 csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-valid-with-signature-of-individual-artifact-p7.csar create mode 100644 csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-individual-p7-signature-common-cert-invalid.csar create mode 100644 csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-individual-p7-signature-common-cert-valid.csar create mode 100644 csarvalidation/src/test/resources/security/signature/testEncodedSignature.sig.p7c create mode 100644 csarvalidation/src/test/resources/security/signature/testSignature.sig.cms create mode 100644 csarvalidation/src/test/resources/security/signature/testSignature.sig.p7b diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/r130206/CsarSourceSecurityValidator.java b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/r130206/CsarSourceSecurityValidator.java index 282b37d..8710c36 100644 --- a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/r130206/CsarSourceSecurityValidator.java +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/r130206/CsarSourceSecurityValidator.java @@ -33,7 +33,7 @@ import java.util.List; public class CsarSourceSecurityValidator { public static final String SIGNATURE_FILE_TYPE = "signature"; - private static final String[] ARTIFACT_SIGNATURE_EXTENSIONS = {".sig.cms"}; + private static final String[] ARTIFACT_SIGNATURE_EXTENSIONS = {".sig.cms",".sig.p7b",".sig.p7c"}; public static final String CERTIFICATE_FILE_TYPE = "certificate"; private static final String[] ARTIFACT_CERTIFICATE_EXTENSIONS = {".cert"}; diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/r130206/Error.java b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/r130206/Error.java index 72b036f..f74b6a5 100644 --- a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/r130206/Error.java +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/r130206/Error.java @@ -170,9 +170,9 @@ public class Error { public static class CSARErrorFailToLoadArtifactSignature extends CSARArchive.CSARError { - public CSARErrorFailToLoadArtifactSignature(String path, String cms) { + public CSARErrorFailToLoadArtifactSignature(String source, String signature) { super("0x4019"); - this.message = String.format("Fail to load signature '%s', for source '%s'!", path, cms); + this.message = String.format("Fail to load signature '%s', for source '%s'!", signature, source); } } diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureDataFactory.java b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureDataFactory.java index 2744bc6..834f0ad 100644 --- a/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureDataFactory.java +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureDataFactory.java @@ -24,23 +24,21 @@ import org.bouncycastle.cms.CMSProcessableByteArray; import org.bouncycastle.cms.CMSSignedData; import org.bouncycastle.cms.CMSTypedData; import org.bouncycastle.cms.SignerInformation; -import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.util.Store; -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.Charset; import java.util.Collection; import java.util.Optional; public class CmsSignatureDataFactory { + private final SignatureFactory signatureFactory = new SignatureFactory(); + public CmsSignatureData createForFirstSigner(final byte[] cmsSignature, final byte[] fileContent) - throws CmsSignatureLoadingException{ + throws CmsSignatureLoadingException { - try (ByteArrayInputStream cmsSignatureStream = new ByteArrayInputStream(cmsSignature)) { - CMSSignedData signedData = getCMSSignedData(fileContent, cmsSignatureStream); + try { + CMSSignedData signedData = getCMSSignedData(fileContent, cmsSignature); Collection signers = signedData.getSignerInfos().getSigners(); Store certificates = signedData.getCertificates(); SignerInformation firstSigner = getFirstSigner(signers); @@ -73,19 +71,10 @@ public class CmsSignatureDataFactory { return cert; } - - private CMSSignedData getCMSSignedData(byte[] innerPackageFileCSAR, ByteArrayInputStream signatureStream) throws IOException, CmsSignatureLoadingException, CMSException { - ContentInfo signature = produceSignature(signatureStream); + private CMSSignedData getCMSSignedData(byte[] innerPackageFileCSAR, byte[] signatureStream) throws IOException, CmsSignatureLoadingException, CMSException { + ContentInfo signature = signatureFactory.createSignature(signatureStream); CMSTypedData signedContent = new CMSProcessableByteArray(innerPackageFileCSAR); return new CMSSignedData(signedContent, signature); } - private ContentInfo produceSignature(ByteArrayInputStream signatureStream) throws IOException, CmsSignatureLoadingException { - Object parsedObject = new PEMParser(new InputStreamReader(signatureStream, Charset.defaultCharset())).readObject(); - if (!(parsedObject instanceof ContentInfo)) { - throw new CmsSignatureLoadingException("Signature is not recognized!"); - } - return ContentInfo.getInstance(parsedObject); - } - } diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/security/SignatureFactory.java b/csarvalidation/src/main/java/org/onap/cvc/csar/security/SignatureFactory.java new file mode 100644 index 0000000..00e9fce --- /dev/null +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/security/SignatureFactory.java @@ -0,0 +1,60 @@ +/* + * Copyright 2021 Nokia + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.onap.cvc.csar.security; + +import org.apache.commons.codec.binary.Base64; +import org.bouncycastle.asn1.cms.ContentInfo; +import org.bouncycastle.openssl.PEMParser; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +public class SignatureFactory { + + public static final String PEM_SIGNATURE_BEGIN_TAG = "-----BEGIN CMS-----"; + public static final String PEM_SIGNATURE_END_TAG = "-----END CMS-----"; + + public ContentInfo createSignature(byte[] signatureStream) throws IOException, CmsSignatureLoadingException { + byte[] pemSignatureStream = convertSignatureToPemIfInDerFormat(signatureStream); + try(ByteArrayInputStream signatureInput = new ByteArrayInputStream(pemSignatureStream)) { + Object parsedObject = new PEMParser(new InputStreamReader(signatureInput)).readPemObject().getContent(); + return ContentInfo.getInstance(parsedObject); + } catch (Exception e) { + throw new CmsSignatureLoadingException("Signature is not recognized!", e); + } + } + + private byte[] convertSignatureToPemIfInDerFormat(byte[] signatureStream) throws IOException { + byte[] encodedSignatureStream = signatureStream.clone(); + if (!Base64.isBase64(signatureStream)) { + encodedSignatureStream = Base64.encodeBase64(encodedSignatureStream); + encodedSignatureStream = wrapWithPemTags(encodedSignatureStream); + } + return encodedSignatureStream; + } + + private byte[] wrapWithPemTags(byte[] encodedSignatureStream) throws IOException { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream( ); + outputStream.write( (PEM_SIGNATURE_BEGIN_TAG + "\n").getBytes() ); + outputStream.write( encodedSignatureStream ); + outputStream.write( ("\n" + PEM_SIGNATURE_END_TAG).getBytes() ); + return outputStream.toByteArray(); + } +} diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206IntegrationTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206IntegrationTest.java index 4d6adc4..0015c02 100644 --- a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206IntegrationTest.java +++ b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206IntegrationTest.java @@ -29,6 +29,8 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.configureTestCase; import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.convertToMessagesList; +import static org.onap.functional.CsarValidationUtility.CERTIFICATION_RULE; +import static org.onap.functional.CsarValidationUtility.createExpectedError; public class VTPValidateCSARR130206IntegrationTest { @@ -630,7 +632,119 @@ public class VTPValidateCSARR130206IntegrationTest { ); } + @Test + public void shouldReturnNoErrorWhenIndividualArtifactHaveP7Signature() throws Exception { + + // given + configureTestCaseForRule130206("pnf/r130206/csar-cert-in-cms-valid-with-signature-of-individual-artifact-p7.csar"); + + // when + testCase.execute(); + + // then + List errors = testCase.getErrors(); + + assertThat(convertToMessagesList(errors)).containsExactlyInAnyOrder( + "Manifest file has invalid signature!" + ); + } + + @Test + public void shouldReturnNoErrorWhenIndividualArtifactHaveP7SignatureInDERFormat() throws Exception { + + // given + configureTestCaseForRule130206("pnf/r130206/csar-cert-in-cms-valid-with-signature-of-individual-artifact-p7-DER.csar"); + + // when + testCase.execute(); + + // then + List errors = testCase.getErrors(); + + assertThat(convertToMessagesList(errors)).containsExactlyInAnyOrder( + "Manifest file has invalid signature!" + ); + } + + @Test + public void shouldReturnNoErrorWhenIndividualArtifactHaveP7SignatureAndUsesCommonCert() throws Exception { + + // given + configureTestCaseForRule130206("pnf/r130206/csar-cert-in-tosca-individual-p7-signature-common-cert-valid.csar"); + + // when + testCase.execute(); + + // then + List errors = testCase.getErrors(); + + assertThat(convertToMessagesList(errors)).containsExactlyInAnyOrder( + "Manifest file has invalid signature!" + ); + } + + @Test + public void shouldReturnErrorWhenIndividualArtifactHaveInvalidP7Signature() throws Exception { + + // given + configureTestCaseForRule130206("pnf/r130206/csar-cert-in-cms-invalid-with-signature-of-individual-artifact-p7.csar"); + + // when + testCase.execute(); + + // then + List errors = testCase.getErrors(); + + assertThat(convertToMessagesList(errors)).containsExactlyInAnyOrder( + "Source 'Files/Yang_module/mynetconf.yang' has incorrect signature!", + "Manifest file has invalid signature!" + ); + } + + @Test + public void shouldReturnErrorWhenIndividualArtifactHaveInvalidP7SignatureAndUsesCommonCert() throws Exception { + + // given + configureTestCaseForRule130206("pnf/r130206/csar-cert-in-tosca-individual-p7-signature-common-cert-invalid.csar"); + + // when + testCase.execute(); + + // then + List errors = testCase.getErrors(); + + assertThat(convertToMessagesList(errors)).containsExactlyInAnyOrder( + "Source 'Files/Yang_module/mynetconf.yang' has incorrect signature!", + "Manifest file has invalid signature!" + ); + } + + @Test + public void shouldReturnMultipleErrorsWhenMultipleIndividualArtifactsHaveInvalidSecurityData() throws Exception { + + // given + configureTestCaseForRule130206("pnf/r130206/csar-cert-in-tosca-multiple-individual-signature.csar"); + + // when + testCase.execute(); + + // then + List errors = testCase.getErrors(); + assertThat(convertToMessagesList(errors)).containsExactlyInAnyOrder( + "Source 'Artifacts/Deployment/Events/RadioNode_Pnf_v1.yaml' has wrong hash!", + "Source 'Artifacts/Deployment/Events/RadioNode_Pnf_v2.yaml' has incorrect signature!", + "Source 'Artifacts/Deployment/Measurements/PM_Dictionary.yml' has 'signature' tag, pointing to non existing file!. Pointed file 'Artifacts/Deployment/Measurements/PM_Dictionary.sig.cms'", + "Source 'Artifacts/Deployment/Yang_module/yang-module1.yang' has 'signature' file with wrong name, signature name: 'yang-module.sig.cms'.Signature should have same name as source file!", + "Source 'Artifacts/Deployment/Yang_module/yang-module1.yang' has 'certificate' file with wrong name, signature name: 'yang-module.cert'.Signature should have same name as source file!", + "Source 'Artifacts/Other/my_script.csh' has incorrect signature!", + "Source 'Artifacts/Informational/user_guide.txt' has 'signature' file located in wrong directory, directory: 'Artifacts/user_guide.sig.cms'.Signature should be in same directory as source file!", + "Source 'Artifacts/Informational/user_guide.txt' has 'certificate' file located in wrong directory, directory: 'Artifacts/user_guide.cert'.Signature should be in same directory as source file!", + "Manifest file has invalid signature!" + ); + } + private void configureTestCaseForRule130206(String filePath) throws OnapCommandException, URISyntaxException { configureTestCase(testCase, filePath, VTP_VALIDATE_SCHEMA, IS_PNF); } + } diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/security/SignatureFactoryTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/security/SignatureFactoryTest.java new file mode 100644 index 0000000..baa88c0 --- /dev/null +++ b/csarvalidation/src/test/java/org/onap/cvc/csar/security/SignatureFactoryTest.java @@ -0,0 +1,159 @@ +/* + * Copyright 2021 Nokia + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.onap.cvc.csar.security; + +import org.bouncycastle.asn1.ASN1Encoding; +import org.bouncycastle.asn1.cms.ContentInfo; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Base64; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SignatureFactoryTest { + + private final static String testPemSignature = "" + + "-----BEGIN CMS-----\n" + + "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" + + "dDrh3CbBGa9nLr6i1jOOp1TxYM8/e2kYbVIl" + + "\n-----END CMS-----"; + + private final static String testPkcs7Signature = "" + + "-----BEGIN PKCS7-----\n" + + "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" + + "dDrh3CbBGa9nLr6i1jOOp1TxYM8/e2kYbVIl" + + "\n-----END PKCS7-----"; + + private SignatureFactory signatureFactory; + + @Before + public void setUp(){ + signatureFactory = new SignatureFactory(); + } + + @Test + public void shouldCreateContentInfoWithProperContentForPEM() throws IOException, CmsSignatureLoadingException { + + // when + ContentInfo contentInfo = signatureFactory.createSignature(testPemSignature.getBytes()); + + // then + final String contentInfoSignature = getContentInfoSignatureAsPem(contentInfo); + assertThat(testPemSignature).contains(contentInfoSignature); + } + + @Test + public void shouldCreateContentInfoWithProperContentForPKCS7() throws IOException, CmsSignatureLoadingException { + + // when + ContentInfo contentInfo = signatureFactory.createSignature(testPkcs7Signature.getBytes()); + + // then + final String contentInfoSignature = getContentInfoSignatureAsPem(contentInfo); + assertThat(testPkcs7Signature).contains(contentInfoSignature); + } + + @Test + public void shouldCreateContentInfoWithProperContentForDecodedPKCS7() throws IOException, CmsSignatureLoadingException { + // given + InputStream signatureAsStream = loadFileFromResources("./security/signature/testEncodedSignature.sig.p7c"); + + // when + ContentInfo contentInfo = signatureFactory.createSignature(signatureAsStream.readAllBytes()); + + // then + final String contentInfoSignature = getContentInfoSignatureAsPem(contentInfo); + assertThat(testPkcs7Signature).contains(contentInfoSignature); + } + + private InputStream loadFileFromResources(String fileFromResources) throws IOException{ + InputStream resourceAsStream = SignatureFactoryTest.class.getClassLoader().getResourceAsStream(fileFromResources); + if(resourceAsStream==null) { + throw new IOException(String.format("fail to load file: %s from resourcer", fileFromResources)); + } + return resourceAsStream; + } + + private String getContentInfoSignatureAsPem(ContentInfo contentInfo) throws IOException { + return new String(Base64.getEncoder().encode(contentInfo.toASN1Primitive().getEncoded(ASN1Encoding.DER))); + } + +} diff --git a/csarvalidation/src/test/java/org/onap/functional/PnfValidationFunctionalTest.java b/csarvalidation/src/test/java/org/onap/functional/PnfValidationFunctionalTest.java index 2038eca..2477377 100644 --- a/csarvalidation/src/test/java/org/onap/functional/PnfValidationFunctionalTest.java +++ b/csarvalidation/src/test/java/org/onap/functional/PnfValidationFunctionalTest.java @@ -258,10 +258,10 @@ public class PnfValidationFunctionalTest { assertThat(ruleValidationResult.warnings).isEmpty(); if (ruleValidationResult.vnfreqName.equals(CERTIFICATION_RULE)) { assertThat(ruleValidationResult.errors) - .containsAll(expectedCertificationErrors); + .containsExactlyInAnyOrderElementsOf(expectedCertificationErrors); } else if (ruleValidationResult.vnfreqName.equals(MANIFEST_FILE_RULE)) { assertThat(ruleValidationResult.errors) - .containsAll(expectedManifestErrors); + .containsExactlyInAnyOrderElementsOf(expectedManifestErrors); } else { assertThat(ruleValidationResult.errors).isEmpty(); } @@ -274,6 +274,10 @@ public class PnfValidationFunctionalTest { // given List expectedCertificationErrors = List.of( + createExpectedError(CERTIFICATION_RULE, "0x4004", + "Source 'Artifacts/Deployment/Events/RadioNode_Pnf_v1.yaml' has wrong hash!"), + createExpectedError(CERTIFICATION_RULE, "0x4020", + "Source 'Artifacts/Deployment/Events/RadioNode_Pnf_v2.yaml' has incorrect signature!"), createExpectedError(CERTIFICATION_RULE, "0x4018", "Source 'Artifacts/Deployment/Measurements/PM_Dictionary.yml' has 'signature' tag, pointing to non existing file!. Pointed file 'Artifacts/Deployment/Measurements/PM_Dictionary.sig.cms'"), createExpectedError(CERTIFICATION_RULE, "0x4023", @@ -338,19 +342,19 @@ public class PnfValidationFunctionalTest { switch (ruleValidationResult.vnfreqName) { case CERTIFICATION_RULE: assertThat(ruleValidationResult.errors) - .containsAll(expectedCertificationErrors); + .containsExactlyInAnyOrderElementsOf(expectedCertificationErrors); break; case MANIFEST_FILE_RULE: assertThat(ruleValidationResult.errors) - .containsAll(expectedManifestErrors); + .containsExactlyInAnyOrderElementsOf(expectedManifestErrors); break; case PM_DICTIONARY_YAML_RULE: assertThat(ruleValidationResult.errors) - .containsAll(expectedPnfDictionaryErrors); + .containsExactlyInAnyOrderElementsOf(expectedPnfDictionaryErrors); break; case NON_MANO_FILES_RULE: assertThat(ruleValidationResult.errors) - .containsAll(expectedNonManoFilesErrors); + .containsExactlyInAnyOrderElementsOf(expectedNonManoFilesErrors); break; default: assertThat(ruleValidationResult.errors).isEmpty(); diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-invalid-with-signature-of-individual-artifact-p7.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-invalid-with-signature-of-individual-artifact-p7.csar new file mode 100644 index 0000000..2b1b48b Binary files /dev/null and b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-invalid-with-signature-of-individual-artifact-p7.csar differ diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-valid-with-signature-of-individual-artifact-p7-DER.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-valid-with-signature-of-individual-artifact-p7-DER.csar new file mode 100644 index 0000000..5277099 Binary files /dev/null and b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-valid-with-signature-of-individual-artifact-p7-DER.csar differ diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-valid-with-signature-of-individual-artifact-p7.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-valid-with-signature-of-individual-artifact-p7.csar new file mode 100644 index 0000000..4f55629 Binary files /dev/null and b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-valid-with-signature-of-individual-artifact-p7.csar differ diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-individual-p7-signature-common-cert-invalid.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-individual-p7-signature-common-cert-invalid.csar new file mode 100644 index 0000000..ad9df38 Binary files /dev/null and b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-individual-p7-signature-common-cert-invalid.csar differ diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-individual-p7-signature-common-cert-valid.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-individual-p7-signature-common-cert-valid.csar new file mode 100644 index 0000000..cbf02d2 Binary files /dev/null and b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-individual-p7-signature-common-cert-valid.csar differ diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-multiple-individual-signature.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-multiple-individual-signature.csar index c2560bd..1b25855 100644 Binary files a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-multiple-individual-signature.csar and b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-multiple-individual-signature.csar differ diff --git a/csarvalidation/src/test/resources/security/signature/testEncodedSignature.sig.p7c b/csarvalidation/src/test/resources/security/signature/testEncodedSignature.sig.p7c new file mode 100644 index 0000000..3709390 Binary files /dev/null and b/csarvalidation/src/test/resources/security/signature/testEncodedSignature.sig.p7c differ diff --git a/csarvalidation/src/test/resources/security/signature/testSignature.sig.cms b/csarvalidation/src/test/resources/security/signature/testSignature.sig.cms new file mode 100644 index 0000000..30612a4 --- /dev/null +++ b/csarvalidation/src/test/resources/security/signature/testSignature.sig.cms @@ -0,0 +1,34 @@ +-----BEGIN CMS----- +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 +dDrh3CbBGa9nLr6i1jOOp1TxYM8/e2kYbVIl +-----END CMS----- diff --git a/csarvalidation/src/test/resources/security/signature/testSignature.sig.p7b b/csarvalidation/src/test/resources/security/signature/testSignature.sig.p7b new file mode 100644 index 0000000..2e00705 --- /dev/null +++ b/csarvalidation/src/test/resources/security/signature/testSignature.sig.p7b @@ -0,0 +1,34 @@ +-----BEGIN PKCS7----- +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 +dDrh3CbBGa9nLr6i1jOOp1TxYM8/e2kYbVIl +-----END PKCS7----- -- cgit 1.2.3-korg