Merge "[OOM-CERT-SERVICE] Add Certification Request functionality"
[oom/platform/cert-service.git] / certService / src / main / java / org / onap / oom / certservice / certification / conversion / OldCertificateModelFactory.java
1 /*
2  * ============LICENSE_START=======================================================
3  * Cert Service
4  * ================================================================================
5  * Copyright (C) 2021 Nokia. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.oom.certservice.certification.conversion;
22
23 import java.security.KeyFactory;
24 import java.security.NoSuchAlgorithmException;
25 import java.security.PrivateKey;
26 import java.security.cert.CertificateEncodingException;
27 import java.security.cert.CertificateParsingException;
28 import java.security.cert.X509Certificate;
29 import java.security.spec.InvalidKeySpecException;
30 import java.security.spec.PKCS8EncodedKeySpec;
31 import org.bouncycastle.asn1.x500.X500Name;
32 import org.bouncycastle.asn1.x509.Certificate;
33 import org.bouncycastle.asn1.x509.GeneralName;
34 import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
35 import org.bouncycastle.util.io.pem.PemObject;
36 import org.onap.oom.certservice.certification.X509CertificateParser;
37 import org.onap.oom.certservice.certification.exception.CertificateDecryptionException;
38 import org.onap.oom.certservice.certification.exception.KeyDecryptionException;
39 import org.onap.oom.certservice.certification.exception.StringToCertificateConversionException;
40 import org.onap.oom.certservice.certification.model.OldCertificateModel;
41 import org.springframework.beans.factory.annotation.Autowired;
42 import org.springframework.stereotype.Service;
43
44 @Service
45 public class OldCertificateModelFactory {
46
47     private static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n";
48     private static final String END_CERTIFICATE = "-----END CERTIFICATE-----\n";
49     private static final PemObjectFactory PEM_OBJECT_FACTORY = new PemObjectFactory();
50
51     private final PemStringToCertificateConverter pemStringToCertificateConverter;
52     private final X509CertificateParser x509CertificateParser;
53
54     @Autowired
55     public OldCertificateModelFactory(PemStringToCertificateConverter pemStringToCertificateConverter,
56         X509CertificateParser x509CertificateParser) {
57         this.pemStringToCertificateConverter = pemStringToCertificateConverter;
58         this.x509CertificateParser = x509CertificateParser;
59     }
60
61     public OldCertificateModel createCertificateModel(StringBase64 base64EncodedCertificate, String encodedOldPrivateKey)
62         throws CertificateDecryptionException {
63         final String certificateString = base64EncodedCertificate.asString()
64             .map(this::getFirstCertificateFromCertificateChain)
65             .orElseThrow(() -> new CertificateDecryptionException("Incorrect certificate, decryption failed"));
66         try {
67             final X509Certificate x509Certificate = pemStringToCertificateConverter.convert(certificateString);
68             final X500Name subjectData = x509CertificateParser.getSubject(x509Certificate);
69             final GeneralName[] sans = x509CertificateParser.getSans(x509Certificate);
70             final Certificate certificate = new JcaX509CertificateHolder(x509Certificate).toASN1Structure();
71             final PrivateKey oldPrivateKey = getOldPrivateKeyObject(encodedOldPrivateKey);
72             return new OldCertificateModel(certificate, subjectData, sans, oldPrivateKey);
73         } catch (StringToCertificateConversionException e) {
74             throw new CertificateDecryptionException("Cannot convert certificate", e);
75
76         } catch (CertificateParsingException e) {
77             throw new CertificateDecryptionException("Cannot read Subject Alternative Names from certificate");
78         } catch (NoSuchAlgorithmException | KeyDecryptionException | CertificateEncodingException | InvalidKeySpecException e) {
79             throw new CertificateDecryptionException("Cannot convert certificate or key", e);
80         }
81     }
82
83     private String getFirstCertificateFromCertificateChain(String certificateChain) {
84         if (doesNotContainCertificates(certificateChain)) {
85             return null;
86         }
87         return certificateChain.split(END_CERTIFICATE)[0] + END_CERTIFICATE;
88     }
89
90     private boolean doesNotContainCertificates(String certificateChain) {
91         return !(certificateChain.contains(BEGIN_CERTIFICATE) && certificateChain.contains(END_CERTIFICATE));
92     }
93
94     private PrivateKey getOldPrivateKeyObject(String encodedOldPrivateKey)
95         throws KeyDecryptionException, InvalidKeySpecException, NoSuchAlgorithmException {
96
97         StringBase64 stringBase64 = new StringBase64(encodedOldPrivateKey);
98         PemObject pemObject = stringBase64.asString()
99             .flatMap(PEM_OBJECT_FACTORY::createPemObject)
100             .orElseThrow(
101                 () -> new KeyDecryptionException("Incorrect Key, decryption failed")
102             );
103         PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pemObject.getContent());
104         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
105         return keyFactory.generatePrivate(keySpec);
106     }
107 }