1 /* 2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package com.ohos.hapsigntool.utils; 17 18 import com.ohos.hapsigntool.error.VerifyCertificateChainException; 19 20 import java.io.File; 21 import java.io.FileInputStream; 22 import java.io.IOException; 23 import java.security.InvalidKeyException; 24 import java.security.NoSuchAlgorithmException; 25 import java.security.NoSuchProviderException; 26 import java.security.SignatureException; 27 import java.security.cert.CertificateException; 28 import java.security.cert.CertificateExpiredException; 29 import java.security.cert.CertificateFactory; 30 import java.security.cert.X509Certificate; 31 import java.security.cert.CertificateNotYetValidException; 32 import java.util.ArrayList; 33 import java.util.Collection; 34 import java.util.Collections; 35 import java.util.List; 36 37 /** 38 * Utils of certificate processing. 39 * 40 * @since 2021/12/28 41 */ 42 public class CertificateUtils { 43 /** 44 * Constructor of Method 45 */ CertificateUtils()46 private CertificateUtils() { 47 } 48 49 /** 50 * Check cert list is cert chain. 51 * 52 * @param certs certs 53 * @throws VerifyCertificateChainException certificates in file are not certificate chain 54 */ verifyCertChain(List<X509Certificate> certs)55 public static void verifyCertChain(List<X509Certificate> certs) throws VerifyCertificateChainException { 56 if (certs.size() <= 1) { 57 return; 58 } 59 for (int i = 1; i < certs.size(); i++) { 60 try { 61 certs.get(i - 1).verify(certs.get(i).getPublicKey()); 62 certs.get(i - 1).checkValidity(); 63 if (!certs.get(i - 1).getIssuerDN().equals(certs.get(i).getSubjectDN())) { 64 throw new CertificateException("verify certificate chain issuer subject failed") ; 65 } 66 if (i == certs.size() - 1) { 67 certs.get(i).checkValidity(); 68 } 69 } catch (CertificateExpiredException | CertificateNotYetValidException e) { 70 throw new VerifyCertificateChainException("The certificate has expired! " + e.getMessage()); 71 } catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException 72 | NoSuchProviderException | SignatureException e) { 73 throw new VerifyCertificateChainException("verify certificate chain failed! " + e.getMessage()); 74 } 75 } 76 } 77 78 /** 79 * Get certificates chains from input file. 80 * 81 * @param certsFile input file 82 * @return list of certificate chain 83 * @throws IOException file is not exist 84 * @throws CertificateException data in file is not certificate 85 * @throws VerifyCertificateChainException certificates in file are not certificate chain 86 */ 87 @SuppressWarnings("unchecked") getCertListFromFile(String certsFile)88 public static List<X509Certificate> getCertListFromFile(String certsFile) throws IOException, CertificateException, 89 VerifyCertificateChainException { 90 try (FileInputStream fileInputStream = FileUtils.openInputStream(new File(certsFile))) { 91 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 92 Collection<X509Certificate> certificates = 93 (Collection<X509Certificate>) cf.generateCertificates(fileInputStream); 94 if (certificates != null && !certificates.isEmpty()) { 95 List<X509Certificate> certs = new ArrayList<X509Certificate>(certificates); 96 CertUtils.sortCertificateChain(certs); 97 verifyCertChain(certs); 98 return certs; 99 } 100 } 101 return Collections.emptyList(); 102 } 103 } 104