From 379eb896b050fbb1f88ca7e736665c573f8c9f74 Mon Sep 17 00:00:00 2001 From: Bogumil Zebek Date: Fri, 31 May 2019 13:58:12 +0200 Subject: Handle signature in cms Change-Id: Ied997305efe347859cbd069f2887f792adc775c0 Issue-ID: VNFSDK-414 Signed-off-by: Zebek Bogumil --- .../cvc/csar/cc/sol004/VTPValidateCSARR787965.java | 12 ++- .../onap/cvc/csar/rsa/RSACertificateValidator.java | 43 ----------- .../onap/cvc/csar/rsa/X509RsaCertification.java | 66 ---------------- .../cvc/csar/security/CmsSignatureValidator.java | 90 ++++++++++++++++++++++ .../security/CmsSignatureValidatorException.java | 28 +++++++ 5 files changed, 123 insertions(+), 116 deletions(-) delete mode 100644 csarvalidation/src/main/java/org/onap/cvc/csar/rsa/RSACertificateValidator.java delete mode 100644 csarvalidation/src/main/java/org/onap/cvc/csar/rsa/X509RsaCertification.java create mode 100644 csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidator.java create mode 100644 csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidatorException.java (limited to 'csarvalidation/src/main/java/org') diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR787965.java b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR787965.java index a5ff4ed..621ede0 100644 --- a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR787965.java +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR787965.java @@ -23,14 +23,12 @@ import org.onap.cli.fw.schema.OnapCommandSchema; import org.onap.cvc.csar.CSARArchive; import org.onap.cvc.csar.FileArchive; import org.onap.cvc.csar.cc.VTPValidateCSARBase; -import org.onap.cvc.csar.rsa.RSACertificateValidator; -import org.onap.cvc.csar.rsa.X509RsaCertification; +import org.onap.cvc.csar.security.CmsSignatureValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Base64; import java.util.Optional; @OnapCommandSchema(schema = "vtp-validate-csar-r787965.yaml") @@ -49,7 +47,7 @@ public class VTPValidateCSARR787965 extends VTPValidateCSARBase { protected void validateCSAR(CSARArchive csar) throws OnapCommandException { try { - final RSACertificateValidator rsaCertificateValidator = new RSACertificateValidator(new X509RsaCertification()); + final CmsSignatureValidator securityManager = new CmsSignatureValidator(); FileArchive.Workspace workspace = csar.getWorkspace(); final Optional pathToCsarFile = workspace.getPathToCsarFile(); @@ -58,10 +56,10 @@ public class VTPValidateCSARR787965 extends VTPValidateCSARBase { if (workspace.isZip() && pathToCsarFile.isPresent() && pathToCertFile.isPresent() && pathToCmsFile.isPresent()) { byte[] csarContent = Files.readAllBytes(pathToCsarFile.get()); - String signature = Base64.getEncoder().encodeToString(Files.readAllBytes(pathToCmsFile.get())); - String publicCertification = Base64.getEncoder().encodeToString(Files.readAllBytes(pathToCertFile.get())); + byte[] signature = Files.readAllBytes(pathToCmsFile.get()); + byte[] publicCertification = Files.readAllBytes(pathToCertFile.get()); - if (!rsaCertificateValidator.isValid(csarContent, signature, publicCertification)) { + if (!securityManager.verifySignedData(signature, publicCertification,csarContent)) { this.errors.add(new CSARErrorInvalidSignature()); } } diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/rsa/RSACertificateValidator.java b/csarvalidation/src/main/java/org/onap/cvc/csar/rsa/RSACertificateValidator.java deleted file mode 100644 index 022f697..0000000 --- a/csarvalidation/src/main/java/org/onap/cvc/csar/rsa/RSACertificateValidator.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019 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.rsa; - - -import java.security.PublicKey; - -public class RSACertificateValidator { - - private final X509RsaCertification x509RsaCertification; - - public RSACertificateValidator(X509RsaCertification x509RsaCertification) { - this.x509RsaCertification = x509RsaCertification; - } - - public boolean isValid(byte [] content, String signature, String publicCertificateContent) throws Exception { - - String publicCert = extractPublicKeyCertificate(publicCertificateContent); - final PublicKey publicKey = this.x509RsaCertification.generatePublicKey(publicCert); - - return this.x509RsaCertification.verify(content,signature,publicKey); - } - - private String extractPublicKeyCertificate(String publicCertificateContent) { - String publicCert = publicCertificateContent.replace("-----BEGIN CERTIFICATE-----\n", ""); - return publicCert.replace("-----END CERTIFICATE-----\n", ""); - } -} diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/rsa/X509RsaCertification.java b/csarvalidation/src/main/java/org/onap/cvc/csar/rsa/X509RsaCertification.java deleted file mode 100644 index 8395221..0000000 --- a/csarvalidation/src/main/java/org/onap/cvc/csar/rsa/X509RsaCertification.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2019 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.rsa; - -import org.apache.commons.codec.binary.Base64; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.PublicKey; -import java.security.Signature; -import java.security.SignatureException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; - -public class X509RsaCertification { - - private static final Logger LOG = LoggerFactory.getLogger(X509RsaCertification.class); - - PublicKey generatePublicKey(String cert) throws CertificateException { - byte[] encodedCert = cert.getBytes(StandardCharsets.UTF_8); - byte[] decodedCert = Base64.decodeBase64(encodedCert); - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - InputStream in = new ByteArrayInputStream(decodedCert); - X509Certificate certificate = (X509Certificate) certFactory.generateCertificate(in); - - LOG.info(String.format("Subject DN : %s", certificate.getSubjectDN().getName())); - LOG.info(String.format("Issuer : %s", certificate.getIssuerDN().getName())); - LOG.info(String.format("Not After: %s", certificate.getNotAfter())); - LOG.info(String.format("Not Before: %s", certificate.getNotBefore())); - LOG.info(String.format("version: %d", certificate.getVersion())); - LOG.info(String.format("serial number : %s", certificate.getSerialNumber())); - - return certificate.getPublicKey(); - } - - boolean verify(byte[] content, String signature, PublicKey publicKey) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { - Signature publicSignature = Signature.getInstance("SHA256withRSA"); - publicSignature.initVerify(publicKey); - publicSignature.update(content); - - byte[] signatureBytes = java.util.Base64.getDecoder().decode(signature); - - return publicSignature.verify(signatureBytes); - } -} diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidator.java b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidator.java new file mode 100644 index 0000000..316c802 --- /dev/null +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidator.java @@ -0,0 +1,90 @@ +/* + * Copyright 2019 + *

+ * 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.cms.ContentInfo; +import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.CMSProcessableByteArray; +import org.bouncycastle.cms.CMSSignedData; +import org.bouncycastle.cms.CMSSignerDigestMismatchException; +import org.bouncycastle.cms.CMSTypedData; +import org.bouncycastle.cms.SignerInformation; +import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.operator.OperatorCreationException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Collection; + +public class CmsSignatureValidator { + + public boolean verifySignedData( + final byte[] signature, + final byte[] certificate, + final byte[] csarFileContent) throws CmsSignatureValidatorException { + + try (ByteArrayInputStream signatureStream = new ByteArrayInputStream(signature)) { + SignerInformation firstSigner = getSignerInformation(csarFileContent, signatureStream); + X509Certificate cert = loadCertificate(certificate); + + return firstSigner.verify(new JcaSimpleSignerInfoVerifierBuilder().build(cert)); + } catch (CMSSignerDigestMismatchException e){ + //message-digest attribute value does not match calculated value + return false; + } + catch (OperatorCreationException | IOException | CMSException e) { + throw new CmsSignatureValidatorException("Unexpected error occurred during signature validation!", e); + } + } + + private SignerInformation getSignerInformation(byte[] innerPackageFileCSAR, ByteArrayInputStream signatureStream) throws IOException, CmsSignatureValidatorException, CMSException { + ContentInfo signature = produceSignature(signatureStream); + CMSTypedData signedContent = new CMSProcessableByteArray(innerPackageFileCSAR); + CMSSignedData signedData = new CMSSignedData(signedContent, signature); + + Collection signers = signedData.getSignerInfos().getSigners(); + return signers.iterator().next(); + } + + private ContentInfo produceSignature(ByteArrayInputStream signatureStream) throws IOException, CmsSignatureValidatorException { + Object parsedObject = new PEMParser(new InputStreamReader(signatureStream)).readObject(); + if (!(parsedObject instanceof ContentInfo)) { + throw new CmsSignatureValidatorException("Signature is not recognized!"); + } + return ContentInfo.getInstance(parsedObject); + } + + + private X509Certificate loadCertificate(byte[] certFile) throws CmsSignatureValidatorException { + try (InputStream in = new ByteArrayInputStream(certFile)) { + CertificateFactory factory = CertificateFactory.getInstance("X.509"); + return (X509Certificate) factory.generateCertificate(in); + } catch (CertificateException | IOException e) { + throw new CmsSignatureValidatorException("Error during loading Certificate from bytes!", e); + } + } + + +} + diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidatorException.java b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidatorException.java new file mode 100644 index 0000000..75cd8de --- /dev/null +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidatorException.java @@ -0,0 +1,28 @@ +/* + * Copyright 2019 + *

+ * 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; + +public class CmsSignatureValidatorException extends Exception { + + public CmsSignatureValidatorException(String s) { + super(s); + } + + public CmsSignatureValidatorException(String s, Throwable t) { + super(s, t); + } +} -- cgit 1.2.3-korg