ArchiveLoader.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2024 Link.it srl (https://link.it).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3, as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openspcoop2.utils.certificate;
import java.io.ByteArrayInputStream;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import org.openspcoop2.utils.UtilsException;
/**
* Certificate
*
* @author Poli Andrea (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class ArchiveLoader {
private ArchiveLoader() {}
public static Certificate load(byte[] content) throws UtilsException {
return loadEngine(ArchiveType.CER, content, -1, null, null, false);
}
public static Certificate loadChain(byte[] content) throws UtilsException {
return loadEngine(ArchiveType.CER, content, -1, null, null, true);
}
public static Certificate load(byte[] content, boolean chain) throws UtilsException {
return loadEngine(ArchiveType.CER, content, -1, null, null, chain);
}
public static Certificate loadFromKeystorePKCS12(byte[] content, int position, String password) throws UtilsException {
return loadEngine(ArchiveType.PKCS12, content, position, null, password, false);
}
public static Certificate loadFromKeystorePKCS12(byte[] content, String alias, String password) throws UtilsException {
return loadEngine(ArchiveType.PKCS12, content, -1, alias, password, false);
}
public static Certificate loadFromKeystoreJKS(byte[] content, int position, String password) throws UtilsException {
return loadEngine(ArchiveType.JKS, content, position, null, password, false);
}
public static Certificate loadFromKeystoreJKS(byte[] content, String alias, String password) throws UtilsException {
return loadEngine(ArchiveType.JKS, content, -1, alias, password, false);
}
public static Certificate load(ArchiveType type, byte[] content, int position, String password) throws UtilsException {
return loadEngine(type, content, position, null, password, false);
}
public static Certificate load(ArchiveType type, byte[] content, String alias, String password) throws UtilsException {
return loadEngine(type, content, -1, alias, password, false);
}
private static Certificate loadEngine(ArchiveType type, byte[] content, int position, String alias, String password, boolean chain) throws UtilsException {
try {
switch (type) {
case JKS:
case PKCS12:
return buildCertificateFromKeyStore(type, content, position, alias, password);
case CER:
return buildCertificateFromCER(content, alias, chain);
default:
break;
}
throw new UtilsException("Certificate not found in archive (type: "+type+")");
}catch(Exception e) {
throw new UtilsException(e.getMessage(),e);
}
}
private static Certificate buildCertificateFromKeyStore(ArchiveType type, byte[] content, int position, String alias, String password) throws UtilsException {
try {
KeyStore ks = KeystoreUtils.readKeystore(content, type.name(), password);
Enumeration<String> en = ks.aliases();
int index = -1;
while (en.hasMoreElements()) {
index ++;
String aliasCheck = en.nextElement();
java.security.cert.Certificate baseCert = ks.getCertificate(aliasCheck);
if(!(baseCert instanceof X509Certificate)) {
if(aliasCheck.equalsIgnoreCase(alias)) {
throw new UtilsException("Certificate ["+alias+"] isn't X509");
}else {
continue;
}
}
X509Certificate cert = (X509Certificate) baseCert;
java.security.cert.Certificate[] baseCertChain = ks.getCertificateChain(aliasCheck);
List<java.security.cert.X509Certificate> certChain = readCertificateChain(baseCertChain);
if(
(aliasCheck.equalsIgnoreCase(alias))
||
(position>=0 && index==position)
) {
return new Certificate(aliasCheck, cert, certChain);
}
}
if(alias!=null) {
throw new UtilsException("Certificate ["+alias+"] not found");
}
else {
throw new UtilsException("Certificate at position ["+position+"] not found");
}
}catch(Exception e) {
throw new UtilsException(e.getMessage(),e);
}
}
private static List<java.security.cert.X509Certificate> readCertificateChain(java.security.cert.Certificate[] baseCertChain) throws UtilsException {
try {
List<java.security.cert.X509Certificate> certChain = null;
if(baseCertChain!=null && baseCertChain.length>0) {
for (int i = 0; i < baseCertChain.length; i++) {
java.security.cert.Certificate check = baseCertChain[i];
if(check instanceof X509Certificate) {
if(certChain==null) {
certChain = new ArrayList<>();
}
certChain.add((X509Certificate) check);
}
}
}
return certChain;
}catch(Exception e) {
throw new UtilsException(e.getMessage(),e);
}
}
private static Certificate buildCertificateFromCER( byte[] content, String alias, boolean chain) throws UtilsException {
try {
if(alias==null) {
alias = "cert";
}
CertificateFactory fact = org.openspcoop2.utils.certificate.CertificateFactory.getCertificateFactory();
if(chain) {
try(ByteArrayInputStream bin = new ByteArrayInputStream(content)){
Collection<? extends java.security.cert.Certificate> certs = fact.generateCertificates(bin);
return loadCertificateChain(certs, alias);
}
}
else {
// provo prima a caricarlo come chain
// I formati pkcs7 devono ad esempio essere caricati tramite la primitiva generateCertificates
Collection<? extends java.security.cert.Certificate> certs = buildCollectionCertificate(fact, content);
if(certs==null || certs.isEmpty()) {
try(ByteArrayInputStream bin = new ByteArrayInputStream(content)){
X509Certificate cer = (X509Certificate) fact.generateCertificate(bin);
return new Certificate(alias, cer);
}
}
else {
return loadCertificateChain(certs, alias);
}
}
}catch(Exception e) {
throw new UtilsException(e.getMessage(),e);
}
}
private static Collection<? extends java.security.cert.Certificate> buildCollectionCertificate(CertificateFactory fact, byte[]content){
Collection<? extends java.security.cert.Certificate> certs = null;
try(ByteArrayInputStream bin = new ByteArrayInputStream(content)){
certs = fact.generateCertificates(bin);
}catch(Exception t) {
// ignore
}
return certs;
}
private static Certificate loadCertificateChain(Collection<? extends java.security.cert.Certificate> certs, String alias) throws UtilsException {
if(certs==null || certs.isEmpty()) {
throw new UtilsException("Certificates not found");
}
int cList = 0;
X509Certificate cer = null;
List<X509Certificate> listChain = null;
for (java.security.cert.Certificate c : certs) {
if(c instanceof X509Certificate) {
X509Certificate tmp = (X509Certificate) c;
if(cList==0) {
cer = tmp;
}
else {
if(listChain==null) {
listChain = new ArrayList<>();
}
listChain.add(tmp);
}
cList++;
}
}
if(listChain!=null) {
return new Certificate(alias, cer, listChain);
}
else {
return new Certificate(alias, cer);
}
}
public static List<String> readAliasesInKeystorePKCS12(byte[] content, String password) throws UtilsException {
return readAliasesEngine(ArchiveType.PKCS12, content, password);
}
public static List<String> readAliasesInKeystoreJKS(byte[] content, String password) throws UtilsException {
return readAliasesEngine(ArchiveType.JKS, content, password);
}
public static List<String> readAliases(ArchiveType type, byte[] content, String password) throws UtilsException {
return readAliasesEngine(type, content, password);
}
private static List<String> readAliasesEngine(ArchiveType type, byte[] content, String password) throws UtilsException {
try {
switch (type) {
case JKS:
case PKCS12:
KeyStore ks = KeystoreUtils.readKeystore(content, type.name(), password);
Enumeration<String> en = ks.aliases();
List<String> list = new ArrayList<>();
while (en.hasMoreElements()) {
String alias = en.nextElement();
list.add(alias);
}
return list;
case CER:
throw new UtilsException("Type '"+type+"' hasn't alias");
default:
break;
}
throw new UtilsException("Certificate not found in archive (type: "+type+")");
}catch(Exception e) {
throw new UtilsException(e.getMessage(),e);
}
}
}