ETSI SOL007 3.3.1 package security option 2

Change-Id: I4e021c517449e6ddf11571c02d0b4bdbc93e7c1e
Issue-ID: SDC-2614
Signed-off-by: andre.schmid <andre.schmid@est.tech>
diff --git a/common-be/pom.xml b/common-be/pom.xml
index 94da6cf..c4489b0 100644
--- a/common-be/pom.xml
+++ b/common-be/pom.xml
@@ -74,6 +74,13 @@
     </dependency>
 
     <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcpkix-jdk15on</artifactId>
+      <version>${bouncycastle.version}</version>
+      <scope>compile</scope>
+    </dependency>
+
+    <dependency>
       <groupId>org.hamcrest</groupId>
       <artifactId>hamcrest</artifactId>
       <version>${hamcrest.version}</version>
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/CertificateManagerImpl.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/CertificateManagerImpl.java
new file mode 100644
index 0000000..9ec8ea8
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/CertificateManagerImpl.java
@@ -0,0 +1,167 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.Key;
+import java.security.Security;
+import java.security.cert.Certificate;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.apache.commons.io.FilenameUtils;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.openecomp.sdc.be.csar.security.api.CertificateManager;
+import org.openecomp.sdc.be.csar.security.api.CertificateReader;
+import org.openecomp.sdc.be.csar.security.api.PrivateKeyReader;
+import org.openecomp.sdc.be.csar.security.api.model.CertificateInfo;
+import org.openecomp.sdc.be.csar.security.exception.CertificateNotFoundException;
+import org.openecomp.sdc.be.csar.security.model.CertificateInfoImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CertificateManagerImpl implements CertificateManager {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(CertificateManagerImpl.class);
+
+    private final PrivateKeyReader privateKeyReader;
+    private final CertificateReader certificateReader;
+    private final Environment environment;
+
+    private Path certificateDirectoryPath;
+    private File certificateDirectory;
+    private final Map<String, CertificateInfo> certificateMap = new HashMap<>();
+
+    public static final String CERT_DIR_ENV_VARIABLE = "SDC_CERT_DIR";
+
+    public CertificateManagerImpl(final PrivateKeyReader privateKeyReader,
+                                  final CertificateReader certificateReader,
+                                  final Environment environment) {
+        this.certificateReader = certificateReader;
+        this.privateKeyReader = privateKeyReader;
+        this.environment = environment;
+        init();
+    }
+
+    private void init() {
+        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
+            Security.addProvider(new BouncyCastleProvider());
+        }
+
+        final String certificateDir = environment.getProperty(CERT_DIR_ENV_VARIABLE);
+        if (certificateDir == null) {
+            LOGGER.warn("Environment variable '{}' was not provided. Could not load certificates.", CERT_DIR_ENV_VARIABLE);
+            return;
+        }
+        try {
+            this.certificateDirectoryPath = Paths.get(certificateDir);
+        } catch (final Exception e) {
+            LOGGER.error("Invalid path '{}' provided in the environment variable '{}'. Could not load certificates.",
+                certificateDir, CERT_DIR_ENV_VARIABLE, e);
+            return;
+        }
+        try {
+            loadCertificateDirectory();
+        } catch (final Exception e) {
+            LOGGER.error("Could not load certificate directory", e);
+            return;
+        }
+        try {
+            loadCertificates();
+        } catch (final Exception e) {
+            LOGGER.error("Could not load certificates", e);
+        }
+    }
+
+    private void loadCertificates() {
+        final File[] files = certificateDirectory.listFiles();
+        if (files == null || files.length == 0) {
+            LOGGER.warn("Certificate directory is empty. No trusted certificate found.");
+            return;
+        }
+
+        final List<File> certFileList = Arrays.stream(files)
+            .filter(file -> "cert".equals(FilenameUtils.getExtension(file.getName())))
+            .collect(Collectors.toList());
+        final List<File> keyFileList = Arrays.stream(files)
+            .filter(file -> "key".equals(FilenameUtils.getExtension(file.getName())))
+            .collect(Collectors.toList());
+
+        if (certFileList.isEmpty()) {
+            LOGGER.error("Certificate directory is empty. No trusted certificate found.");
+            return;
+        }
+
+        certFileList.forEach(certFile -> {
+            final String baseFileName = FilenameUtils.getBaseName(certFile.getName());
+            final Certificate certificate = loadCertificate(certFile);
+            final Optional<File> keyFileOptional = keyFileList.stream().filter(
+                keyFile1 -> FilenameUtils.getBaseName(keyFile1.getName())
+                    .equals(baseFileName)).findFirst();
+            keyFileOptional.ifPresentOrElse(
+                keyFile -> {
+                    final CertificateInfoImpl certificateInfo =
+                        new CertificateInfoImpl(certFile, certificate, keyFile, loadPrivateKey(keyFile));
+                    if (certificateInfo.isValid()) {
+                        certificateMap.put(baseFileName, certificateInfo);
+                    }
+                },
+                () -> {
+                    final CertificateInfoImpl certificateInfo = new CertificateInfoImpl(certFile, certificate);
+                    if (certificateInfo.isValid()) {
+                        certificateMap.put(baseFileName, new CertificateInfoImpl(certFile, certificate));
+                    }
+                }
+            );
+        });
+    }
+
+    private void loadCertificateDirectory() {
+        final File file = certificateDirectoryPath.toFile();
+        if (!file.exists() || !file.isDirectory()) {
+            final String errorMsg =
+                String.format("Provided certificate path '%s' is not a directory or does not exist",
+                    certificateDirectoryPath);
+            throw new CertificateNotFoundException(errorMsg);
+        }
+        this.certificateDirectory = file;
+    }
+
+    private Certificate loadCertificate(final File certFile) {
+        return certificateReader.loadCertificate(certFile);
+    }
+
+    private Key loadPrivateKey(final File privateKeyFile) {
+        return privateKeyReader.loadPrivateKey(privateKeyFile);
+    }
+
+    @Override
+    public Optional<CertificateInfo> getCertificate(final String certName) {
+        return Optional.ofNullable(certificateMap.get(certName));
+    }
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/PrivateKeyReaderImpl.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/PrivateKeyReaderImpl.java
new file mode 100644
index 0000000..a6ee61d
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/PrivateKeyReaderImpl.java
@@ -0,0 +1,53 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security;
+
+import java.io.File;
+import java.io.FileReader;
+import java.security.Key;
+import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openssl.PEMParser;
+import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
+import org.openecomp.sdc.be.csar.security.api.PrivateKeyReader;
+import org.openecomp.sdc.be.csar.security.exception.LoadPrivateKeyException;
+import org.openecomp.sdc.be.csar.security.exception.UnsupportedKeyFormatException;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PrivateKeyReaderImpl implements PrivateKeyReader {
+
+    @Override
+    public Key loadPrivateKey(final File privateKeyFile) {
+        try (final PEMParser pemParser = new PEMParser(new FileReader(privateKeyFile))) {
+            final Object pemObject = pemParser.readObject();
+            final JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME);
+            if (pemObject instanceof PrivateKeyInfo) {
+                return converter.getPrivateKey((PrivateKeyInfo) pemObject);
+            }
+        } catch (final Exception e) {
+            final String errorMsg = "Could not load the private key from given file '%s'";
+            throw new LoadPrivateKeyException(String.format(errorMsg, privateKeyFile), e);
+        }
+        final String errorMsg = "Could not load the private key from given file '%s'. Unsupported format.";
+        throw new UnsupportedKeyFormatException(String.format(errorMsg, privateKeyFile));
+    }
+
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/Sha256WithRsaCmsContentSigner.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/Sha256WithRsaCmsContentSigner.java
new file mode 100644
index 0000000..7b7273e
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/Sha256WithRsaCmsContentSigner.java
@@ -0,0 +1,98 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.cms.ContentInfo;
+import org.bouncycastle.cert.jcajce.JcaCertStore;
+import org.bouncycastle.cms.CMSProcessableByteArray;
+import org.bouncycastle.cms.CMSSignedData;
+import org.bouncycastle.cms.CMSSignedDataGenerator;
+import org.bouncycastle.cms.CMSTypedData;
+import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
+import org.openecomp.sdc.be.csar.security.api.CmsContentSigner;
+import org.openecomp.sdc.be.csar.security.exception.CmsSignatureException;
+import org.springframework.stereotype.Component;
+
+@Component
+public class Sha256WithRsaCmsContentSigner implements CmsContentSigner {
+
+    @Override
+    public byte[] signData(final byte[] data, final Certificate signingCertificate, final Key signingKey)
+        throws CmsSignatureException {
+
+        final CMSTypedData cmsData = new CMSProcessableByteArray(data);
+        final JcaCertStore certStore = createCertificateStore(signingCertificate);
+        try {
+            final ContentSigner contentSigner
+                = new JcaContentSignerBuilder("SHA256withRSA")
+                .setProvider(BouncyCastleProvider.PROVIDER_NAME).build((PrivateKey) signingKey);
+
+            final CMSSignedDataGenerator cmsGenerator = new CMSSignedDataGenerator();
+            cmsGenerator.addSignerInfoGenerator(
+                new JcaSignerInfoGeneratorBuilder(
+                    new JcaDigestCalculatorProviderBuilder().setProvider(BouncyCastleProvider.PROVIDER_NAME).build()
+                ).build(contentSigner, (X509Certificate) signingCertificate)
+            );
+            cmsGenerator.addCertificates(certStore);
+
+            final CMSSignedData cms = cmsGenerator.generate(cmsData, false);
+            return cms.getEncoded();
+        } catch (final Exception e) {
+            throw new CmsSignatureException("Could not sign the given data", e);
+        }
+    }
+
+    @Override
+    public String formatToPemSignature(final byte[] signedData) throws CmsSignatureException {
+        final StringWriter sw = new StringWriter();
+        try (final JcaPEMWriter jcaPEMWriter = new JcaPEMWriter(sw)) {
+            final ContentInfo ci = ContentInfo.getInstance(ASN1Primitive.fromByteArray(signedData));
+            jcaPEMWriter.writeObject(ci);
+        } catch (final IOException e) {
+            throw new CmsSignatureException("Could not convert signed data to PEM format", e);
+        }
+        return sw.toString();
+    }
+
+    private JcaCertStore createCertificateStore(final Certificate signingCertificate) throws CmsSignatureException {
+        try {
+            return new JcaCertStore(Collections.singletonList(signingCertificate));
+        } catch (final CertificateEncodingException e) {
+            final String errorMsg = String
+                .format("Could not create certificate store from certificate '%s'", signingCertificate);
+            throw new CmsSignatureException(errorMsg, e);
+        }
+    }
+
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/X509CertificateReader.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/X509CertificateReader.java
new file mode 100644
index 0000000..b8e95e7
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/X509CertificateReader.java
@@ -0,0 +1,57 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import org.openecomp.sdc.be.csar.security.api.CertificateReader;
+import org.openecomp.sdc.be.csar.security.exception.LoadCertificateException;
+import org.springframework.stereotype.Component;
+
+@Component
+public class X509CertificateReader implements CertificateReader {
+
+    /**
+     * Reads X.509 certificate file.
+     *
+     * @param certFile the certificate file
+     * @return the read certificate
+     * @throws LoadCertificateException when an error has occurred while reading the certificate
+     */
+    @Override
+    public Certificate loadCertificate(final File certFile) {
+        try (final FileInputStream fi = new FileInputStream(certFile)) {
+            return buildCertificate(fi);
+        } catch (final Exception e) {
+            final String errorMsg = "Could not load the certificate from given file '%s'";
+            throw new LoadCertificateException(String.format(errorMsg, certFile), e);
+        }
+    }
+
+    private Certificate buildCertificate(final InputStream certificateInputStream) throws CertificateException {
+        final CertificateFactory factory = CertificateFactory.getInstance("X.509");
+        return factory.generateCertificate(certificateInputStream);
+    }
+
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CertificateManager.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CertificateManager.java
new file mode 100644
index 0000000..53437f3
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CertificateManager.java
@@ -0,0 +1,29 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security.api;
+
+import java.util.Optional;
+import org.openecomp.sdc.be.csar.security.api.model.CertificateInfo;
+
+public interface CertificateManager {
+
+    Optional<CertificateInfo> getCertificate(String certName);
+
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CertificateReader.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CertificateReader.java
new file mode 100644
index 0000000..4c32fa1
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CertificateReader.java
@@ -0,0 +1,34 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security.api;
+
+import java.io.File;
+import java.security.cert.Certificate;
+
+public interface CertificateReader {
+
+    /**
+     * Reads a certificate file.
+     *
+     * @param certFile the certificate file
+     * @return the read certificate
+     */
+    Certificate loadCertificate(File certFile);
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CmsContentSigner.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CmsContentSigner.java
new file mode 100644
index 0000000..37bd988
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CmsContentSigner.java
@@ -0,0 +1,32 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security.api;
+
+import java.security.Key;
+import java.security.cert.Certificate;
+import org.openecomp.sdc.be.csar.security.exception.CmsSignatureException;
+
+public interface CmsContentSigner {
+
+    byte[] signData(byte[] data, Certificate signingCertificate, Key signingKey)
+        throws CmsSignatureException;
+
+    String formatToPemSignature(byte[] signedData) throws CmsSignatureException;
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/PrivateKeyReader.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/PrivateKeyReader.java
new file mode 100644
index 0000000..3e8c406
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/PrivateKeyReader.java
@@ -0,0 +1,38 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security.api;
+
+import java.io.File;
+import java.security.Key;
+import org.openecomp.sdc.be.csar.security.exception.LoadPrivateKeyException;
+import org.openecomp.sdc.be.csar.security.exception.UnsupportedKeyFormatException;
+
+public interface PrivateKeyReader {
+
+    /**
+     * Reads a given private file.
+     *
+     * @param privateKeyFile the private key file
+     * @return the read private key
+     * @throws LoadPrivateKeyException       when an error has occurred while reading the private key
+     * @throws UnsupportedKeyFormatException when the private key is not supported
+     */
+    Key loadPrivateKey(final File privateKeyFile);
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/model/CertificateInfo.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/model/CertificateInfo.java
new file mode 100644
index 0000000..5b234cc
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/model/CertificateInfo.java
@@ -0,0 +1,46 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security.api.model;
+
+import java.io.File;
+import java.security.Key;
+import java.security.cert.Certificate;
+
+public interface CertificateInfo {
+
+    String getName();
+
+    File getCertificateFile();
+
+    Certificate getCertificate();
+
+    File getPrivateKeyFile();
+
+    Key getPrivateKey();
+
+    /**
+     * Check if the certificate is valid.
+     *
+     * @return {@code true} if the certificate is valid. {@code false} otherwise.
+     * @throws UnsupportedOperationException when the certificate is not supported
+     */
+    boolean isValid();
+
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/CertificateNotFoundException.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/CertificateNotFoundException.java
new file mode 100644
index 0000000..a2175f3
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/CertificateNotFoundException.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security.exception;
+
+public class CertificateNotFoundException extends RuntimeException {
+
+    public CertificateNotFoundException(final String message) {
+        super(message);
+    }
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/CmsSignatureException.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/CmsSignatureException.java
new file mode 100644
index 0000000..6bc49d6
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/CmsSignatureException.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security.exception;
+
+public class CmsSignatureException extends Exception {
+
+    public CmsSignatureException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/LoadCertificateException.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/LoadCertificateException.java
new file mode 100644
index 0000000..3cd1062
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/LoadCertificateException.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security.exception;
+
+public class LoadCertificateException extends RuntimeException {
+
+    public LoadCertificateException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/LoadPrivateKeyException.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/LoadPrivateKeyException.java
new file mode 100644
index 0000000..00681bc
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/LoadPrivateKeyException.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security.exception;
+
+public class LoadPrivateKeyException extends RuntimeException {
+
+    public LoadPrivateKeyException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/UnsupportedKeyFormatException.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/UnsupportedKeyFormatException.java
new file mode 100644
index 0000000..d30f6f2
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/UnsupportedKeyFormatException.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security.exception;
+
+public class UnsupportedKeyFormatException extends RuntimeException {
+
+    public UnsupportedKeyFormatException(final String message) {
+        super(message);
+    }
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/model/CertificateInfoImpl.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/model/CertificateInfoImpl.java
new file mode 100644
index 0000000..f7b2faf
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/model/CertificateInfoImpl.java
@@ -0,0 +1,70 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security.model;
+
+import java.io.File;
+import java.security.Key;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import lombok.Getter;
+import org.apache.commons.io.FilenameUtils;
+import org.openecomp.sdc.be.csar.security.api.model.CertificateInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Getter
+public class CertificateInfoImpl implements CertificateInfo {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(CertificateInfoImpl.class);
+
+    private final String name;
+    private final File certificateFile;
+    private final Certificate certificate;
+    private File privateKeyFile;
+    private Key privateKey;
+
+    public CertificateInfoImpl(final File certificateFile, final Certificate certificate) {
+        this.certificateFile = certificateFile;
+        this.certificate = certificate;
+        this.name = FilenameUtils.getBaseName(certificateFile.getName());
+    }
+
+    public CertificateInfoImpl(final File certificateFile, final Certificate certificate,
+                               final File privateKeyFile, final Key privateKey) {
+        this(certificateFile, certificate);
+        this.privateKeyFile = privateKeyFile;
+        this.privateKey = privateKey;
+    }
+
+    @Override
+    public boolean isValid() {
+        if("X.509".equals(certificate.getType())) {
+            try {
+                ((X509Certificate) certificate).checkValidity();
+                return true;
+            } catch (final Exception e) {
+                LOGGER.warn("Invalid certificate '{}'", certificateFile.getAbsolutePath(), e);
+                return false;
+            }
+        }
+        throw new UnsupportedOperationException(String.format("Certificate type '%s' not supported", certificate.getType()));
+    }
+
+}
diff --git a/common-be/src/test/java/org/openecomp/sdc/be/csar/security/CertificateManagerImplTest.java b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/CertificateManagerImplTest.java
new file mode 100644
index 0000000..6287c0e
--- /dev/null
+++ b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/CertificateManagerImplTest.java
@@ -0,0 +1,141 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.when;
+import static org.openecomp.sdc.be.csar.security.CertificateManagerImpl.CERT_DIR_ENV_VARIABLE;
+
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.Optional;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.csar.security.api.CertificateReader;
+import org.openecomp.sdc.be.csar.security.api.PrivateKeyReader;
+import org.openecomp.sdc.be.csar.security.api.model.CertificateInfo;
+import org.springframework.core.env.Environment;
+
+class CertificateManagerImplTest {
+
+    @Mock
+    private Environment environment;
+    @Mock
+    private PrivateKeyReader privateKeyReader;
+    @Mock
+    private CertificateReader certificateReader;
+    @Mock
+    private X509Certificate certificateMock;
+    private CertificateManagerImpl certificateManager;
+
+    static Path certificateFolderPath;
+
+    @BeforeAll
+    static void beforeAll() {
+        final String resourceFolder = "certificateManager";
+        final URL certificateManager = CertificateManagerImplTest.class.getClassLoader().getResource(resourceFolder);
+        if (certificateManager == null) {
+            fail("Could not find resource folder " + resourceFolder);
+        }
+        certificateFolderPath = Paths.get(certificateManager.getPath());
+    }
+
+    @BeforeEach
+    void setUp() throws CertificateNotYetValidException, CertificateExpiredException {
+        MockitoAnnotations.initMocks(this);
+        when(environment.getProperty(CERT_DIR_ENV_VARIABLE)).thenReturn(certificateFolderPath.toString());
+        when(certificateMock.getType()).thenReturn("X.509");
+        doNothing().when(certificateMock).checkValidity();
+        when(certificateReader.loadCertificate(ArgumentMatchers.any())).thenReturn(certificateMock);
+        certificateManager = new CertificateManagerImpl(privateKeyReader, certificateReader, environment);
+    }
+
+    @Test
+    void getCertificateSuccessTest() {
+        final String certificateName = "fakeCert1";
+        final Optional<CertificateInfo> certificateOpt = certificateManager.getCertificate(certificateName);
+        assertThat(certificateOpt.isPresent(), is(true));
+        final CertificateInfo certificateInfo = certificateOpt.get();
+        assertThat(certificateInfo.getName(), is(certificateName));
+        assertThat(certificateInfo.getPrivateKeyFile(), is(notNullValue()));
+        assertThat(certificateInfo.getPrivateKeyFile().getAbsolutePath(),
+            is(certificateFolderPath.resolve(certificateName + ".key").toString()));
+        assertThat(certificateInfo.getCertificateFile(), is(notNullValue()));
+        assertThat(certificateInfo.getCertificateFile().getAbsolutePath(),
+            is(certificateFolderPath.resolve(certificateName + ".cert").toString()));
+    }
+
+    @Test
+    void initCertificateSuccessTest() {
+        final String certificateName1 = "fakeCert1";
+        final String certificateName2 = "fakeCert2";
+        final String certificateName3 = "fakeCert3";
+        assertThat("Certificate " + certificateName1 + " should be present",
+            certificateManager.getCertificate(certificateName1).isPresent(), is(true));
+        assertThat("Certificate " + certificateName2 + " should be present",
+            certificateManager.getCertificate(certificateName2).isPresent(), is(true));
+        assertThat("Certificate " + certificateName3 + " should not be present",
+            certificateManager.getCertificate(certificateName3).isEmpty(), is(true));
+    }
+
+    @Test
+    void invalidCertificateFolderTest() {
+        final String certificateName1 = "fakeCert1";
+        when(environment.getProperty(CERT_DIR_ENV_VARIABLE)).thenReturn("/an/invalid/folder");
+        final CertificateManagerImpl certificateManager =
+            new CertificateManagerImpl(privateKeyReader, certificateReader, environment);
+        assertThat("Certificate " + certificateName1 + " should be present",
+            certificateManager.getCertificate(certificateName1).isPresent(), is(false));
+    }
+
+    @Test
+    void noEnvironmentVariableConfiguredTest() {
+        final String certificateName1 = "fakeCert1";
+        when(environment.getProperty(CERT_DIR_ENV_VARIABLE)).thenReturn(null);
+        final CertificateManagerImpl certificateManager =
+            new CertificateManagerImpl(privateKeyReader, certificateReader, environment);
+        assertThat("Certificate " + certificateName1 + " should be present",
+            certificateManager.getCertificate(certificateName1).isPresent(), is(false));
+    }
+
+    @Test
+    void loadCertificateExceptionTest() {
+        final String certificateName1 = "fakeCert1";
+        when(certificateReader.loadCertificate(any())).thenThrow(new RuntimeException());
+        final CertificateManagerImpl certificateManager =
+            new CertificateManagerImpl(privateKeyReader, certificateReader, environment);
+        assertThat("Certificate " + certificateName1 + " should be present",
+            certificateManager.getCertificate(certificateName1).isPresent(), is(false));
+    }
+
+}
\ No newline at end of file
diff --git a/common-be/src/test/java/org/openecomp/sdc/be/csar/security/PrivateKeyReaderImplTest.java b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/PrivateKeyReaderImplTest.java
new file mode 100644
index 0000000..7bd44cf
--- /dev/null
+++ b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/PrivateKeyReaderImplTest.java
@@ -0,0 +1,95 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.File;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.Key;
+import java.security.Security;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openecomp.sdc.be.csar.security.exception.LoadPrivateKeyException;
+import org.openecomp.sdc.be.csar.security.exception.UnsupportedKeyFormatException;
+
+class PrivateKeyReaderImplTest {
+
+    private PrivateKeyReaderImpl privateKeyReader;
+
+    @BeforeEach
+    void setUp() {
+        privateKeyReader = new PrivateKeyReaderImpl();
+        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
+            Security.addProvider(new BouncyCastleProvider());
+        }
+    }
+
+    @AfterEach
+    void tearDown() {
+        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) != null) {
+            Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
+        }
+    }
+
+    @Test
+    void loadPrivateKeySuccessTest() {
+        final Path certPath = Paths.get("certificateManager", "realCert", "realCert1.key");
+        final URL resource = getClass().getClassLoader().getResource(certPath.toString());
+        if (resource == null) {
+            fail("Could not find resource " + certPath.toString());
+        }
+        final Key privateKey = privateKeyReader.loadPrivateKey(new File(resource.getPath()));
+        assertNotNull(privateKey);
+    }
+
+    @Test
+    void loadInvalidKeyFilePathTest() {
+        final String invalidFilePath = "aaaa";
+        final File keyFile = new File(invalidFilePath);
+        final LoadPrivateKeyException actualException = assertThrows(LoadPrivateKeyException.class,
+            () -> privateKeyReader.loadPrivateKey(keyFile));
+        assertThat(actualException.getMessage(),
+            is(String.format("Could not load the private key from given file '%s'", invalidFilePath)));
+    }
+
+    @Test
+    void loadInvalidKeyFileTest() {
+        final Path certPath = Paths.get("certificateManager", "fakeCert1.key");
+        final URL resource = getClass().getClassLoader().getResource(certPath.toString());
+        if (resource == null) {
+            fail("Could not find resource " + certPath.toString());
+        }
+        final File keyFile = new File(resource.getPath());
+        final UnsupportedKeyFormatException actualException = assertThrows(UnsupportedKeyFormatException.class,
+            () -> privateKeyReader.loadPrivateKey(keyFile));
+        assertThat(actualException.getMessage(),
+            is(String.format("Could not load the private key from given file '%s'. Unsupported format.",
+                resource.getPath())));
+    }
+}
\ No newline at end of file
diff --git a/common-be/src/test/java/org/openecomp/sdc/be/csar/security/Sha256WithRsaCmsContentSignerTest.java b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/Sha256WithRsaCmsContentSignerTest.java
new file mode 100644
index 0000000..2f0031d
--- /dev/null
+++ b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/Sha256WithRsaCmsContentSignerTest.java
@@ -0,0 +1,119 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.Key;
+import java.security.Security;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import org.bouncycastle.cms.CMSException;
+import org.bouncycastle.cms.CMSProcessableByteArray;
+import org.bouncycastle.cms.CMSSignedData;
+import org.bouncycastle.cms.SignerInformation;
+import org.bouncycastle.cms.SignerInformationStore;
+import org.bouncycastle.cms.SignerInformationVerifier;
+import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openecomp.sdc.be.csar.security.api.CertificateReader;
+import org.openecomp.sdc.be.csar.security.api.PrivateKeyReader;
+import org.openecomp.sdc.be.csar.security.exception.CmsSignatureException;
+
+class Sha256WithRsaCmsContentSignerTest {
+
+    private Sha256WithRsaCmsContentSigner cmsContentSigner;
+    private PrivateKeyReader privateKeyReader;
+    private CertificateReader certificateReader;
+
+    private static final Path testFilesPath = Path.of("certificateManager", "signerTest");
+    private static final Path certFilesPath = Path.of("certificateManager", "realCert");
+
+    @BeforeEach
+    void setUp() {
+        Security.addProvider(new BouncyCastleProvider());
+        cmsContentSigner = new Sha256WithRsaCmsContentSigner();
+        privateKeyReader = new PrivateKeyReaderImpl();
+        certificateReader = new X509CertificateReader();
+    }
+
+    @AfterEach
+    void tearDown() {
+        Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
+    }
+
+    @Test
+    void signDataSuccessTest() throws OperatorCreationException, CMSException, IOException, CmsSignatureException {
+        final File certFile = getResourceFile(certFilesPath.resolve("realCert1.cert"));
+        final File keyFile = getResourceFile(certFilesPath.resolve("realCert1.key"));
+        final File fileToSign = getResourceFile(testFilesPath.resolve("fileToSign.txt"));
+        final Key privateKey = privateKeyReader.loadPrivateKey(keyFile);
+        final Certificate certificate = certificateReader.loadCertificate(certFile);
+        final byte[] actualSignatureBytes = cmsContentSigner
+            .signData(Files.readAllBytes(fileToSign.toPath()), certificate, privateKey);
+
+        assertTrue(verifySignature(Files.readAllBytes(fileToSign.toPath()), actualSignatureBytes,
+            (X509Certificate) certificate));
+    }
+
+    @Test
+    void signDataInvalidCertAndKeyTest() {
+        assertThrows(CmsSignatureException.class,
+            () -> cmsContentSigner.signData(null, null, null));
+    }
+
+    private boolean verifySignature(byte[] contentBytes, byte[] signatureBytes, X509Certificate certificate)
+        throws CMSException, OperatorCreationException {
+
+        final CMSSignedData cms = new CMSSignedData(new CMSProcessableByteArray(contentBytes), signatureBytes);
+        final SignerInformationStore signers = cms.getSignerInfos();
+        final SignerInformationVerifier signerInformationVerifier =
+            new JcaSimpleSignerInfoVerifierBuilder()
+                .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(certificate);
+        for (final SignerInformation signer : signers.getSigners()) {
+            if (!signer.verify(signerInformationVerifier)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private File getResourceFile(final Path testResourcePath) {
+        final URL resource = getClass().getClassLoader().getResource(testResourcePath.toString());
+        if (resource == null) {
+            fail("Could not load the file " + testResourcePath.toString());
+        }
+
+        return new File(resource.getPath());
+    }
+
+}
\ No newline at end of file
diff --git a/common-be/src/test/java/org/openecomp/sdc/be/csar/security/X509CertificateReaderTest.java b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/X509CertificateReaderTest.java
new file mode 100644
index 0000000..3235739
--- /dev/null
+++ b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/X509CertificateReaderTest.java
@@ -0,0 +1,81 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.File;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.cert.Certificate;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openecomp.sdc.be.csar.security.exception.LoadCertificateException;
+
+class X509CertificateReaderTest {
+
+    private X509CertificateReader certificateReader;
+
+    @BeforeEach
+    void setUp() {
+        certificateReader = new X509CertificateReader();
+    }
+
+    @Test
+    void loadCertificateSuccessTest() {
+        final Path certPath = Paths.get("certificateManager", "realCert", "realCert1.cert");
+        final URL resource = getClass().getClassLoader().getResource(certPath.toString());
+        if (resource == null) {
+            fail("Could not find resource " + certPath.toString());
+        }
+        final Certificate certificate = certificateReader.loadCertificate(new File(resource.getPath()));
+        assertNotNull(certificate);
+    }
+
+    @Test
+    void loadInvalidCertificateFilePathTest() {
+        final String invalidFilePath = "aaaa";
+        final File certFile = new File(invalidFilePath);
+        final LoadCertificateException actualException = assertThrows(LoadCertificateException.class,
+            () -> certificateReader.loadCertificate(certFile));
+        assertThat(actualException.getMessage(),
+            is(String.format("Could not load the certificate from given file '%s'", invalidFilePath)));
+    }
+
+    @Test
+    void loadInvalidCertificateFileTest() {
+        final Path certPath = Paths.get("certificateManager", "fakeCert1.cert");
+        System.out.println(certPath.toString());
+        final URL resource = getClass().getClassLoader().getResource(certPath.toString());
+        if (resource == null) {
+            fail("Could not find resource " + certPath.toString());
+        }
+        final File certFile = new File(resource.getPath());
+        final LoadCertificateException actualException = assertThrows(LoadCertificateException.class,
+            () -> certificateReader.loadCertificate(certFile));
+        assertThat(actualException.getMessage(),
+            is(String.format("Could not load the certificate from given file '%s'", resource.getPath())));
+    }
+}
\ No newline at end of file
diff --git a/common-be/src/test/java/org/openecomp/sdc/be/csar/security/model/CertificateInfoImplTest.java b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/model/CertificateInfoImplTest.java
new file mode 100644
index 0000000..6b09413
--- /dev/null
+++ b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/model/CertificateInfoImplTest.java
@@ -0,0 +1,69 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.security.model;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+class CertificateInfoImplTest {
+
+    @Mock
+    private X509Certificate certificate;
+
+    @BeforeEach
+    void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    void isValidTest() throws CertificateNotYetValidException, CertificateExpiredException {
+        when(certificate.getType()).thenReturn("X.509");
+        doNothing().when(certificate).checkValidity();
+        final CertificateInfoImpl certificateInfo = new CertificateInfoImpl(new File(""), certificate);
+        assertTrue(certificateInfo.isValid());
+        doThrow(CertificateExpiredException.class).when(certificate).checkValidity();
+        assertFalse(certificateInfo.isValid());
+    }
+
+    @Test
+    void unsupportedCertificateTypeTest() {
+        final String certificateType = "unknown";
+        when(certificate.getType()).thenReturn(certificateType);
+        final CertificateInfoImpl certificateInfo = new CertificateInfoImpl(new File(""), certificate);
+        final UnsupportedOperationException actualException =
+            assertThrows(UnsupportedOperationException.class, certificateInfo::isValid);
+        assertEquals(actualException.getMessage(),
+            String.format("Certificate type '%s' not supported", certificateType));
+    }
+}
diff --git a/common-be/src/test/resources/certificateManager/fakeCert1.cert b/common-be/src/test/resources/certificateManager/fakeCert1.cert
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/common-be/src/test/resources/certificateManager/fakeCert1.cert
diff --git a/common-be/src/test/resources/certificateManager/fakeCert1.key b/common-be/src/test/resources/certificateManager/fakeCert1.key
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/common-be/src/test/resources/certificateManager/fakeCert1.key
diff --git a/common-be/src/test/resources/certificateManager/fakeCert2.cert b/common-be/src/test/resources/certificateManager/fakeCert2.cert
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/common-be/src/test/resources/certificateManager/fakeCert2.cert
diff --git a/common-be/src/test/resources/certificateManager/fakeCert3.key b/common-be/src/test/resources/certificateManager/fakeCert3.key
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/common-be/src/test/resources/certificateManager/fakeCert3.key
diff --git a/common-be/src/test/resources/certificateManager/realCert/realCert1.cert b/common-be/src/test/resources/certificateManager/realCert/realCert1.cert
new file mode 100644
index 0000000..ae7d518
--- /dev/null
+++ b/common-be/src/test/resources/certificateManager/realCert/realCert1.cert
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEAzCCAuugAwIBAgIUZqdsy8mtirp4AGnTopg9rb3NXcEwDQYJKoZIhvcNAQEL
+BQAwgY8xCzAJBgNVBAYTAkVVMRAwDgYDVQQIDAdOb3doZXJlMRIwEAYDVQQHDAlT
+b21ld2hlcmUxDTALBgNVBAoMBEFDTUUxDDAKBgNVBAsMA1NEQzEVMBMGA1UEAwwM
+c2RjLm9uYXAub3JnMSYwJAYJKoZIhvcNAQkBFhdvbmFwLXNkY0BsaXN0cy5vbmFw
+Lm9yZzAgFw0yMTAyMTYxNDQ2NThaGA8yMDcxMDIwNDE0NDY1OFowgY8xCzAJBgNV
+BAYTAkVVMRAwDgYDVQQIDAdOb3doZXJlMRIwEAYDVQQHDAlTb21ld2hlcmUxDTAL
+BgNVBAoMBEFDTUUxDDAKBgNVBAsMA1NEQzEVMBMGA1UEAwwMc2RjLm9uYXAub3Jn
+MSYwJAYJKoZIhvcNAQkBFhdvbmFwLXNkY0BsaXN0cy5vbmFwLm9yZzCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBANAWK6fjuOq6Wgxwh6QqK0YB9ahjPRj0
+ik/l86AokwyawpgY/iC2xXw+9Etq91C6plYy8BlbYIcv/+KoiteL4YgME9Hk1lwK
+GEceNGwvLKzU5/fTX1BP4qpVi3aB5zCAWa9MhCk+UI/aIeERKFP9XHAx/wuAUq/x
+OP4HLxgLuX/A7Trld3RjjaMYOLjbfJjPFN3lrvfQ02fy5DlJfWG3ASTOOEfdHt1g
+wfOLuzl2l5R34p+zwQKid+2cyKXYs0owZu7Dz9OTWLVxZcLiYEGz8Y3gmmHVhXy+
+TPpvl5wPEajOQBUMksdOric0dIfKjJCMJqFzILv1dfZCr3843MYN3oMCAwEAAaNT
+MFEwHQYDVR0OBBYEFJ6mFarA/5ISm7nZimLshzCH/0F8MB8GA1UdIwQYMBaAFJ6m
+FarA/5ISm7nZimLshzCH/0F8MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBAGUzF4W1vHfksW9qSYqtc8xuM+lV1WrdOW7pX7JkIihUv3Z4jMqysrU4
+nj2iVBG5dPNm9v5GtaeK1ESnVilcdMSYTj/F34/MXJ0iZy1UR0j0IBSrR7JjbTAD
+aYH1sx00hH13U8GMZInnmenmwziOQgBwhhCjLMblUY2vQ4O5MGwZG0VW2e3mUcq1
+HBC69yRMx9jQ+Iof6+rHnCLZXTjcl+65IxXSbKhofvpPJMVXFlmV3TdDdONuvKpS
+051z/ISD6/SEWEvF9ZwAnZvJ/5yPqGzKgyC7rp8zJL+N3VLfr+la1D1w7qgoyFTi
+drptEMCzLOk4OuM8PX8l2kY0G+gQD1o=
+-----END CERTIFICATE-----
diff --git a/common-be/src/test/resources/certificateManager/realCert/realCert1.key b/common-be/src/test/resources/certificateManager/realCert/realCert1.key
new file mode 100644
index 0000000..a31579a
--- /dev/null
+++ b/common-be/src/test/resources/certificateManager/realCert/realCert1.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDQFiun47jquloM
+cIekKitGAfWoYz0Y9IpP5fOgKJMMmsKYGP4gtsV8PvRLavdQuqZWMvAZW2CHL//i
+qIrXi+GIDBPR5NZcChhHHjRsLyys1Of3019QT+KqVYt2gecwgFmvTIQpPlCP2iHh
+EShT/VxwMf8LgFKv8Tj+By8YC7l/wO065Xd0Y42jGDi423yYzxTd5a730NNn8uQ5
+SX1htwEkzjhH3R7dYMHzi7s5dpeUd+Kfs8EConftnMil2LNKMGbuw8/Tk1i1cWXC
+4mBBs/GN4Jph1YV8vkz6b5ecDxGozkAVDJLHTq4nNHSHyoyQjCahcyC79XX2Qq9/
+ONzGDd6DAgMBAAECggEANLj5VK+JIcgXmsFETN72WeWTNZf3WgRTqwzLXpAJOg9Y
+MKtccDN+9A0LXrR6dzTjgkGjvfj+CyKpReeITja97PeKagr+GRHhtts7UxHc0uma
+4JrosnObLadBD8S4K/zJPHY5oi2MwfX10Y3EVwuByVeRlHtt9/A5jXuKfiAyXuCw
+42AT6GUFxntwcKhJSQEcy2B9FwvnF5BDDQKyRVD1McrIj/g7+fiyOpqBXGxk+VYX
+6GjYb0kWR+lVexPBP4fgSs6Yx9EroDqzXAolH94NQfb93sOJuawtNVhkEgjE9hec
+NumdpHMXhXGP0WI/jhicz4gaBDGyEwuSqUxMnfqNyQKBgQDyFx715F3iz2yfnsUQ
+xU7KheUjN0g/vhrcir31L9NuhRpWoBJyRUDeXekuCaDF2ElUXJAdUTMGWDwXxlLx
+aa5b8LPBL4pGvNRakfT1TJrViUm3A9wC4EO8l0IIpoYAEt8nstaw4pMEWLOSSKH/
+O2wG+v1h1/Xfd+ruTbmcBn6yLwKBgQDcCuSQoheMZrb6Hq+i+99LF3ZHVqJKUUCI
+XRnH3fhwhnMrsR9EshOVRtex0aAdl1GUWCAoVt4ZNom5m7b2qRji0gx8npwA0jxD
+CSDUw68Jy3MzQxDMPWNRI38P2r46CslNqCkEGlebbgHEJ0qzp2tIfN25pO6EXfjx
+wk9afY5n7QKBgQCG0Wtzgn7qfZs/dTrHsSnEzTYjG3lHzkXFRhqtfbngVY2qajB7
+pKeQbnoaIlB/fYiwy2+SdBLXWLH2h4LPYIwyNWTVk/UMmcIkwh3JsaSUgIUlv6d5
+jo0KbK3ghWQgjGHsCMNY9ITtKbyvHXXh3qS1andLUuphTbXuiihwhIlwDwKBgD9P
+QwP6HxxeUTcVrSMPpOdOENHlszv+tLqHTuuaieiWRnzDsWNqeQfyIg0faxoYd3hf
+AqGYnL5UWrv0eWfuryJTnRQd7nSuCHihH7kXtDz1NGgDW8nnv7OQqvY80Y6Rm+mk
+AGkVyy8FL6zoQS3/dXadto27ToT3JLEqXvqCNX7hAoGAPfNcJtXJXrXh9P3JZqkM
+pa8nRqUW0MeRt3v8rLqi4D7J6kW1Rkz5AhjiKkp1EwtE0IbGRI1EPhxT5DCMKlIy
+UX7VfP8nf+wb6dLHQ0s4oB20y5J6T7FAkD+50dE6Q/6fAl/2MkE+/R0npKRVhOlc
+eXIeBGzSc7p92K1p/vRMOZg=
+-----END PRIVATE KEY-----
diff --git a/common-be/src/test/resources/certificateManager/signerTest/fileToSign.txt b/common-be/src/test/resources/certificateManager/signerTest/fileToSign.txt
new file mode 100644
index 0000000..cf34721
--- /dev/null
+++ b/common-be/src/test/resources/certificateManager/signerTest/fileToSign.txt
@@ -0,0 +1 @@
+This is a file to be signed.
diff --git a/common-be/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/common-be/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000..ca6ee9c
--- /dev/null
+++ b/common-be/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1 @@
+mock-maker-inline
\ No newline at end of file