ArchiveLoader.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */

  20. package org.openspcoop2.utils.certificate;

  21. import java.io.ByteArrayInputStream;
  22. import java.security.KeyStore;
  23. import java.security.cert.CertificateFactory;
  24. import java.security.cert.X509Certificate;
  25. import java.util.ArrayList;
  26. import java.util.Collection;
  27. import java.util.Enumeration;
  28. import java.util.List;

  29. import org.openspcoop2.utils.UtilsException;

  30. /**
  31.  * Certificate
  32.  *
  33.  * @author Poli Andrea (apoli@link.it)
  34.  * @author $Author$
  35.  * @version $Rev$, $Date$
  36.  */
  37. public class ArchiveLoader {
  38.    
  39.     private ArchiveLoader() {}

  40.     public static Certificate load(byte[] content) throws UtilsException {
  41.         return loadEngine(ArchiveType.CER, content, -1, null, null, false);
  42.     }
  43.     public static Certificate loadChain(byte[] content) throws UtilsException {
  44.         return loadEngine(ArchiveType.CER, content, -1, null, null, true);
  45.     }
  46.     public static Certificate load(byte[] content, boolean chain) throws UtilsException {
  47.         return loadEngine(ArchiveType.CER, content, -1, null, null, chain);
  48.     }
  49.    
  50.     public static Certificate loadFromKeystorePKCS12(byte[] content, int position, String password) throws UtilsException {
  51.         return loadEngine(ArchiveType.PKCS12, content, position, null, password, false);
  52.     }
  53.     public static Certificate loadFromKeystorePKCS12(byte[] content, String alias, String password) throws UtilsException {
  54.         return loadEngine(ArchiveType.PKCS12, content, -1, alias, password, false);
  55.     }
  56.    
  57.     public static Certificate loadFromKeystoreJKS(byte[] content, int position, String password) throws UtilsException {
  58.         return loadEngine(ArchiveType.JKS, content, position, null, password, false);
  59.     }
  60.     public static Certificate loadFromKeystoreJKS(byte[] content, String alias, String password) throws UtilsException {
  61.         return loadEngine(ArchiveType.JKS, content, -1, alias, password, false);
  62.     }
  63.    
  64.     public static Certificate load(ArchiveType type, byte[] content, int position, String password) throws UtilsException {
  65.         return loadEngine(type, content, position, null, password, false);
  66.     }
  67.     public static Certificate load(ArchiveType type, byte[] content, String alias, String password) throws UtilsException {
  68.         return loadEngine(type, content, -1, alias, password, false);
  69.     }
  70.     private static Certificate loadEngine(ArchiveType type, byte[] content, int position, String alias, String password, boolean chain) throws UtilsException {
  71.        
  72.         try {
  73.        
  74.             switch (type) {
  75.             case JKS:
  76.             case PKCS12:
  77.                 return buildCertificateFromKeyStore(type, content, position, alias, password);
  78.             case CER:
  79.                 return buildCertificateFromCER(content, alias, chain);
  80.             default:
  81.                 break;
  82.             }
  83.            
  84.             throw new UtilsException("Certificate not found in archive (type: "+type+")");
  85.            
  86.         }catch(Exception e) {
  87.             throw new UtilsException(e.getMessage(),e);
  88.         }
  89.     }
  90.     private static Certificate buildCertificateFromKeyStore(ArchiveType type, byte[] content, int position, String alias, String password) throws UtilsException {
  91.         try {
  92.             KeyStore ks = KeystoreUtils.readKeystore(content, type.name(), password);
  93.            
  94.             Enumeration<String> en = ks.aliases();
  95.             int index = -1;
  96.             while (en.hasMoreElements()) {
  97.                 index ++;
  98.                 String aliasCheck = en.nextElement();
  99.                 java.security.cert.Certificate baseCert = ks.getCertificate(aliasCheck);
  100.                 if(!(baseCert instanceof X509Certificate)) {
  101.                     if(aliasCheck.equalsIgnoreCase(alias)) {
  102.                         throw new UtilsException("Certificate ["+alias+"] isn't X509");
  103.                     }else {
  104.                         continue;
  105.                     }
  106.                 }
  107.                 X509Certificate cert = (X509Certificate) baseCert;
  108.                 java.security.cert.Certificate[] baseCertChain = ks.getCertificateChain(aliasCheck);
  109.                 List<java.security.cert.X509Certificate> certChain = readCertificateChain(baseCertChain);
  110.                    
  111.                 if(
  112.                     (aliasCheck.equalsIgnoreCase(alias))
  113.                     ||
  114.                     (position>=0 && index==position)
  115.                     ) {
  116.                     return new Certificate(aliasCheck, cert, certChain);
  117.                 }
  118.             }
  119.            
  120.             if(alias!=null) {
  121.                 throw new UtilsException("Certificate ["+alias+"] not found");
  122.             }
  123.             else {
  124.                 throw new UtilsException("Certificate at position ["+position+"] not found");
  125.             }
  126.         }catch(Exception e) {
  127.             throw new UtilsException(e.getMessage(),e);
  128.         }
  129.     }
  130.     private static List<java.security.cert.X509Certificate> readCertificateChain(java.security.cert.Certificate[] baseCertChain) throws UtilsException {
  131.         try {
  132.             List<java.security.cert.X509Certificate> certChain = null;
  133.             if(baseCertChain!=null && baseCertChain.length>0) {
  134.                 for (int i = 0; i < baseCertChain.length; i++) {
  135.                     java.security.cert.Certificate check = baseCertChain[i];
  136.                     if(check instanceof X509Certificate) {
  137.                         if(certChain==null) {
  138.                             certChain = new ArrayList<>();
  139.                         }
  140.                         certChain.add((X509Certificate) check);
  141.                     }
  142.                 }
  143.             }
  144.             return certChain;
  145.         }catch(Exception e) {
  146.             throw new UtilsException(e.getMessage(),e);
  147.         }
  148.     }
  149.     private static Certificate buildCertificateFromCER( byte[] content, String alias, boolean chain) throws UtilsException {
  150.         try {
  151.             if(alias==null) {
  152.                 alias = "cert";
  153.             }
  154.            
  155.             CertificateFactory fact = org.openspcoop2.utils.certificate.CertificateFactory.getCertificateFactory();
  156.             if(chain) {
  157.                 try(ByteArrayInputStream bin = new ByteArrayInputStream(content)){
  158.                     Collection<? extends java.security.cert.Certificate> certs = fact.generateCertificates(bin);
  159.                     return loadCertificateChain(certs, alias);
  160.                 }
  161.             }
  162.             else {
  163.                 // provo prima a caricarlo come chain
  164.                 // I formati pkcs7 devono ad esempio essere caricati tramite la primitiva generateCertificates
  165.                 Collection<? extends java.security.cert.Certificate> certs = buildCollectionCertificate(fact, content);
  166.                
  167.                 if(certs==null || certs.isEmpty()) {
  168.                     try(ByteArrayInputStream bin = new ByteArrayInputStream(content)){
  169.                         X509Certificate cer = (X509Certificate) fact.generateCertificate(bin);
  170.                         return new Certificate(alias, cer);
  171.                     }
  172.                 }
  173.                 else {
  174.                     return loadCertificateChain(certs, alias);
  175.                 }
  176.             }
  177.         }catch(Exception e) {
  178.             throw new UtilsException(e.getMessage(),e);
  179.         }
  180.     }
  181.     private static Collection<? extends java.security.cert.Certificate> buildCollectionCertificate(CertificateFactory fact, byte[]content){
  182.         Collection<? extends java.security.cert.Certificate> certs = null;
  183.         try(ByteArrayInputStream bin = new ByteArrayInputStream(content)){
  184.             certs = fact.generateCertificates(bin);
  185.         }catch(Exception t) {
  186.             // ignore
  187.         }
  188.         return certs;
  189.     }
  190.    
  191.     private static Certificate loadCertificateChain(Collection<? extends java.security.cert.Certificate> certs, String alias) throws UtilsException {
  192.         if(certs==null || certs.isEmpty()) {
  193.             throw new UtilsException("Certificates not found");
  194.         }
  195.         int cList = 0;
  196.         X509Certificate cer = null;
  197.         List<X509Certificate> listChain = null;
  198.         for (java.security.cert.Certificate c : certs) {
  199.             if(c instanceof X509Certificate) {
  200.                 X509Certificate tmp = (X509Certificate) c;
  201.                 if(cList==0) {
  202.                     cer = tmp;
  203.                 }
  204.                 else {
  205.                     if(listChain==null) {
  206.                         listChain = new ArrayList<>();
  207.                     }
  208.                     listChain.add(tmp);
  209.                 }
  210.                 cList++;
  211.             }
  212.         }
  213.         if(listChain!=null) {
  214.             return new Certificate(alias, cer, listChain);
  215.         }
  216.         else {
  217.             return new Certificate(alias, cer);
  218.         }
  219.     }
  220.    
  221.     public static List<String> readAliasesInKeystorePKCS12(byte[] content, String password) throws UtilsException {
  222.         return readAliasesEngine(ArchiveType.PKCS12, content, password);
  223.     }
  224.     public static List<String> readAliasesInKeystoreJKS(byte[] content, String password) throws UtilsException {
  225.         return readAliasesEngine(ArchiveType.JKS, content, password);
  226.     }
  227.     public static List<String> readAliases(ArchiveType type, byte[] content, String password) throws UtilsException {
  228.         return readAliasesEngine(type, content, password);
  229.     }
  230.     private static List<String> readAliasesEngine(ArchiveType type, byte[] content, String password) throws UtilsException {
  231.        
  232.         try {
  233.        
  234.             switch (type) {
  235.             case JKS:
  236.             case PKCS12:
  237.            
  238.                 KeyStore ks = KeystoreUtils.readKeystore(content, type.name(), password);
  239.                
  240.                 Enumeration<String> en = ks.aliases();
  241.                 List<String> list = new ArrayList<>();
  242.                 while (en.hasMoreElements()) {
  243.                     String alias = en.nextElement();
  244.                     list.add(alias);
  245.                 }
  246.                 return list;
  247.    
  248.             case CER:
  249.                
  250.                 throw new UtilsException("Type '"+type+"' hasn't alias");
  251.                
  252.             default:
  253.                 break;
  254.             }
  255.            
  256.             throw new UtilsException("Certificate not found in archive (type: "+type+")");
  257.            
  258.         }catch(Exception e) {
  259.             throw new UtilsException(e.getMessage(),e);
  260.         }
  261.     }  
  262. }