CertificateUtils.java
- /*
- * GovWay - A customizable API Gateway
- * https://govway.org
- *
- * Copyright (c) 2005-2025 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.security.PrivateKey;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.Enumeration;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import javax.security.auth.x500.X500Principal;
- import org.apache.xml.security.utils.RFC2253Parser;
- import org.openspcoop2.utils.Utilities;
- import org.openspcoop2.utils.UtilsException;
- import org.openspcoop2.utils.UtilsMultiException;
- import org.openspcoop2.utils.io.Base64Utilities;
- import org.openspcoop2.utils.io.HexBinaryUtilities;
- import org.openspcoop2.utils.resources.Charset;
- import org.slf4j.Logger;
- import org.springframework.web.util.UriUtils;
- /**
- * CertificateUtils
- *
- * @author Poli Andrea (apoli@link.it)
- * @author $Author$
- * @version $Rev$, $Date$
- */
- public class CertificateUtils {
-
- private CertificateUtils() {}
- public static void printCertificate(StringBuilder bf,List<java.security.cert.X509Certificate> certs){
- printCertificate(bf, certs, false);
- }
- public static void printCertificate(StringBuilder bf,List<java.security.cert.X509Certificate> certs, boolean addPrefix){
- if(!certs.isEmpty()) {
- java.security.cert.X509Certificate[] certsArray = certs.toArray(new java.security.cert.X509Certificate[1]);
- printCertificate(bf, certsArray, addPrefix);
- }
- else {
- bf.append("X509Certificates: "+0+"\n");
- }
- }
-
- public static void printCertificate(StringBuilder bf,java.security.cert.X509Certificate[] certs){
- printCertificate(bf, certs, false);
- }
- public static void printCertificate(StringBuilder bf,java.security.cert.X509Certificate[] certs, boolean addPrefix){
- bf.append("X509Certificates: "+certs.length+"\n");
- for (int i = 0; i < certs.length; i++) {
- java.security.cert.X509Certificate cert = certs[i];
- printCertificate(bf, cert, i+"", addPrefix);
- }
- }
-
- public static void printCertificate(StringBuilder bf,java.security.cert.X509Certificate cert, String name){
- printCertificate(bf, cert, name, false);
- }
- public static void printCertificate(StringBuilder bf,java.security.cert.X509Certificate cert, String name, boolean addPrefix){
- String prefix = "";
- if(addPrefix) {
- prefix = "Cert["+name+"].";
- }
- bf.append("#### X509Certificate["+name+"]\n");
- bf.append("\t"+prefix+"toString()="+cert.toString()+"\n");
- bf.append("\t"+prefix+"getType()="+cert.getType()+"\n");
- bf.append("\t"+prefix+"getVersion()="+cert.getVersion()+"\n");
-
- if(cert.getIssuerDN()!=null){
- bf.append("\t"+prefix+"cert.getIssuerDN().toString()="+cert.getIssuerDN().toString()+"\n");
- bf.append("\t"+prefix+"cert.getIssuerDN().getName()="+cert.getIssuerDN().getName()+"\n");
- }
- else{
- bf.append("\t"+prefix+"cert.getIssuerDN() is null"+"\n");
- }
-
- if(cert.getIssuerX500Principal()!=null){
- bf.append("\t"+prefix+"getIssuerX500Principal().toString()="+cert.getIssuerX500Principal().toString()+"\n");
- bf.append("\t"+prefix+"getIssuerX500Principal().getName()="+cert.getIssuerX500Principal().getName()+"\n");
- bf.append("\t"+prefix+"getIssuerX500Principal().getName(X500Principal.CANONICAL)="+cert.getIssuerX500Principal().getName(X500Principal.CANONICAL)+"\n");
- bf.append("\t"+prefix+"getIssuerX500Principal().getName(X500Principal.RFC1779)="+cert.getIssuerX500Principal().getName(X500Principal.RFC1779)+"\n");
- bf.append("\t"+prefix+"getIssuerX500Principal().getName(X500Principal.RFC2253)="+cert.getIssuerX500Principal().getName(X500Principal.RFC2253)+"\n");
- /** Map<String,String> oidMapCanonical = new HashMap<>();
- bf.append("\t"+prefix+"getIssuerX500Principal().getName(X500Principal.CANONICAL,oidMapCanonical)="+
- cert.getIssuerX500Principal().getName(X500Principal.CANONICAL,oidMapCanonical));
- if(oidMapCanonical!=null && oidMapCanonical.size()>0){
- Iterator<String> it = oidMapCanonical.keySet().iterator();
- while (it.hasNext()) {
- String key = (String) it.next();
- String value = oidMapCanonical.get(key);
- bf.append("\t"+prefix+"getIssuerX500Principal() ["+key+"]=["+value+"]"+"\n");
- }
- }*/
- }
- else{
- bf.append("\t"+prefix+"cert.getIssuerX500Principal() is null"+"\n");
- }
-
- if(cert.getSubjectDN()!=null){
- bf.append("\t"+prefix+"getSubjectDN().toString()="+cert.getSubjectDN().toString()+"\n");
- bf.append("\t"+prefix+"getSubjectDN().getName()="+cert.getSubjectDN().getName()+"\n");
- }
- else{
- bf.append("\t"+prefix+"cert.getSubjectDN() is null"+"\n");
- }
-
- bf.append("\t"+prefix+"getSerialNumber()="+cert.getSerialNumber()+"\n");
- bf.append("\t"+prefix+"getNotAfter()="+cert.getNotAfter()+"\n");
- bf.append("\t"+prefix+"getNotBefore()="+cert.getNotBefore()+"\n");
-
- if(cert.getSubjectX500Principal()!=null){
- bf.append("\t"+prefix+"getSubjectX500Principal().toString()="+cert.getSubjectX500Principal().toString()+"\n");
- bf.append("\t"+prefix+"getSubjectX500Principal().getName()="+cert.getSubjectX500Principal().getName()+"\n");
- bf.append("\t"+prefix+"getSubjectX500Principal().getName(X500Principal.CANONICAL)="+cert.getSubjectX500Principal().getName(X500Principal.CANONICAL)+"\n");
- bf.append("\t"+prefix+"getSubjectX500Principal().getName(X500Principal.RFC1779)="+cert.getSubjectX500Principal().getName(X500Principal.RFC1779)+"\n");
- bf.append("\t"+prefix+"getSubjectX500Principal().getName(X500Principal.RFC2253)="+cert.getSubjectX500Principal().getName(X500Principal.RFC2253)+"\n");
- /** Map<String,String> oidMapCanonical = new HashMap<>();
- bf.append("\t"+prefix+"getSubjectX500Principal().getName(X500Principal.CANONICAL,oidMapCanonical)="+
- cert.getSubjectX500Principal().getName(X500Principal.CANONICAL,oidMapCanonical));
- if(oidMapCanonical!=null && oidMapCanonical.size()>0){
- Iterator<String> it = oidMapCanonical.keySet().iterator();
- while (it.hasNext()) {
- String key = (String) it.next();
- String value = oidMapCanonical.get(key);
- bf.append("\t"+prefix+"getSubjectX500Principal() ["+key+"]=["+value+"]"+"\n");
- }
- }*/
- }
- else{
- bf.append("\t"+prefix+"cert.getSubjectX500Principal() is null"+"\n");
- }
- }
-
-
-
-
-
-
- /* UTILITY SSL */
-
- private static final boolean TRIM_VALUE_BEFORE_SAVE_DB = true;
-
- private static void debug(Logger log, String msg) {
- if(log!=null) {
- log.debug(msg);
- }
- }
- private static String getAnalisiTypePrefixString(String principal, PrincipalType type) {
- return "("+principal+") Analisi "+type+" ";
- }
-
- public static boolean sslVerify(String principalPresenteNellaConfigurazione, String principalArrivatoConnessioneSSL, PrincipalType type, Logger log) throws UtilsException{
- if(log!=null) {
- debug(log, "SSL VERIFY CONF["+principalPresenteNellaConfigurazione+"] SSL["+principalArrivatoConnessioneSSL+"]");
- }
- /** System.out.println("SSL VERIFY CONF["+principalPresenteNellaConfigurazione+"] SSL["+principalArrivatoConnessioneSSL+"]"); */
- // Costruzione key=value
- Map<String, List<String>> hashPrincipalArrivatoConnessioneSSL = CertificateUtils.getPrincipalIntoMap(principalArrivatoConnessioneSSL, type);
- Map<String, List<String>> hashPrincipalPresenteNellaConfigurazione = CertificateUtils.getPrincipalIntoMap(principalPresenteNellaConfigurazione, type);
- if(!sslVerifyCheckSize(principalPresenteNellaConfigurazione, principalArrivatoConnessioneSSL, type,
- hashPrincipalArrivatoConnessioneSSL, hashPrincipalPresenteNellaConfigurazione, log)) {
- return false;
- }
- for (Map.Entry<String,List<String>> entry : hashPrincipalArrivatoConnessioneSSL.entrySet()) {
- String key = entry.getKey();
-
- if(!hashPrincipalPresenteNellaConfigurazione.containsKey(key)){
- /** System.out.println("KEY ["+key+"] non presente"); */
- if(log!=null) {
- List<String> lKeys = new ArrayList<>();
- lKeys.addAll(hashPrincipalPresenteNellaConfigurazione.keySet());
- debug(log, "sslVerify key["+key+"] non trovata in "+type+" "+"Configurazione["+principalPresenteNellaConfigurazione+"]"+", key riscontrate: "+
- lKeys);
- }
- return false;
- }
- // Prendo valori
- List<String> connessioneSSLValueList = hashPrincipalArrivatoConnessioneSSL.get(key);
- List<String> configurazioneInternaValueList = hashPrincipalPresenteNellaConfigurazione.get(key);
- if(connessioneSSLValueList.size() != configurazioneInternaValueList.size()){
- /** System.out.println("LUNGHEZZA DIVERSA KEY ["+key+"]"); */
- if(log!=null) {
- debug(log, "sslVerify "+type+" key["+key+"] trovata in Configurazione["+principalPresenteNellaConfigurazione+"]("+configurazioneInternaValueList.size()+
- ") SSL["+principalArrivatoConnessioneSSL+"]("+connessioneSSLValueList.size()+"): lunghezza differente");
- }
- return false;
- }
-
- // Ordino Valori
- Collections.sort(connessioneSSLValueList);
- Collections.sort(configurazioneInternaValueList);
-
- // confronto valori
- if(!sslVerifyCheckValues(key, type, connessioneSSLValueList, configurazioneInternaValueList, log)) {
- return false;
- }
-
- }
- /** System.out.println("SSL RETURN TRUE"); */
- return true;
- }
- private static boolean sslVerifyCheckSize(String principalPresenteNellaConfigurazione, String principalArrivatoConnessioneSSL, PrincipalType type,
- Map<String, List<String>> hashPrincipalArrivatoConnessioneSSL, Map<String, List<String>> hashPrincipalPresenteNellaConfigurazione, Logger log) {
- if(hashPrincipalArrivatoConnessioneSSL.size() != hashPrincipalPresenteNellaConfigurazione.size()){
- /** System.out.println("LUNGHEZZA DIVERSA"); */
- if(log!=null) {
- debug(log, "sslVerify "+type+" "+"Configurazione["+principalPresenteNellaConfigurazione+"]"+"("+hashPrincipalPresenteNellaConfigurazione.size()+
- ") SSL["+principalArrivatoConnessioneSSL+"]("+hashPrincipalArrivatoConnessioneSSL.size()+"): lunghezza differente");
- }
- return false;
- }
- return true;
- }
- private static boolean sslVerifyCheckValues(String key, PrincipalType type, List<String> connessioneSSLValueList, List<String> configurazioneInternaValueList, Logger log) {
- for (int i = 0; i < connessioneSSLValueList.size(); i++) {
- String connessioneSSLValue = connessioneSSLValueList.get(i);
- String configurazioneInternaValue = configurazioneInternaValueList.get(i);
-
- // Normalizzo caratteri escape
- while(connessioneSSLValue.contains("\\/")){
- connessioneSSLValue = connessioneSSLValue.replace("\\/", "/");
- }
- while(connessioneSSLValue.contains("\\,")){
- connessioneSSLValue = connessioneSSLValue.replace("\\,", ",");
- }
- while(configurazioneInternaValue.contains("\\/")){
- configurazioneInternaValue = configurazioneInternaValue.replace("\\/", "/");
- }
- while(configurazioneInternaValue.contains("\\,")){
- configurazioneInternaValue = configurazioneInternaValue.replace("\\,", ",");
- }
-
- if(!connessioneSSLValue.equals(configurazioneInternaValue)){
- if(log!=null) {
- debug(log, "sslVerify key["+key+"] "+type+" Configurazione["+configurazioneInternaValue+"] SSL["+connessioneSSLValue+"] not match");
- }
- /** System.out.println("VALUE SSL["+connessioneSSLValue+"]=CONF["+configurazioneInternaValue+"] non match"); */
- return false;
- }
- }
- return true;
- }
- public static String formatPrincipal(String principal, PrincipalType type) throws UtilsException{
- /** System.out.println("PRIMA ["+principal+"]"); */
-
- // Autenticazione SSL deve essere LIKE
- Map<String, List<String>> hashPrincipal = CertificateUtils.getPrincipalIntoMap(principal, type);
- StringBuilder bf = new StringBuilder();
- bf.append("/");
- for (Map.Entry<String,List<String>> entry : hashPrincipal.entrySet()) {
-
- String key = entry.getKey();
-
- List<String> listValues = hashPrincipal.get(key);
- for (String value : listValues) {
- bf.append(CertificateUtils.formatKeyPrincipal(key));
- bf.append("=");
- bf.append(CertificateUtils.formatValuePrincipal(value));
- bf.append("/");
- }
-
- }
- /** System.out.println("DOPO ["+bf.toString()+"]"); */
- return bf.toString();
- }
-
- public static Map<String, String> formatPrincipalToMap(String principal, PrincipalType type) throws UtilsException{
- Map<String, String> returnMap = new HashMap<>();
- Map<String, List<String>> hashPrincipal = CertificateUtils.getPrincipalIntoMap(principal, type);
- for (Map.Entry<String,List<String>> entry : hashPrincipal.entrySet()) {
-
- String key = entry.getKey();
-
- List<String> listValues = hashPrincipal.get(key);
- for (String value : listValues) {
- String keyFormat = CertificateUtils.formatKeyPrincipal(key);
- String valueFormat = CertificateUtils.formatValuePrincipal(value);
- returnMap.put(keyFormat, valueFormat);
- }
-
- }
- return returnMap;
- }
- public static void validaPrincipal(String principalParam, PrincipalType type) throws UtilsException{
-
- /** System.out.println("PRIMA VALIDAZIONE ["+principalParam+"]"); */
-
- String principal = principalParam;
- UtilsException normalizedException = null;
- try{
- String tmp = normalizePrincipal(principalParam);
- principal = tmp;
- }catch(UtilsException e){
- /** System.out.println("ERRORE: "+e.getMessage());
- // non voglio rilanciare l'eccezione, verra' segnalata l'eccezione puntuale.
- // Se cosi' non fosse solo in fondo viene sollevata l'eccezione. */
- normalizedException = e;
- }
-
- /** System.out.println("DOPOP VALIDAZIONE ["+principal+"]"); */
-
- boolean commaFound = contains(principal, ",");
- boolean slashFound = contains(principal, "/");
- if(commaFound && slashFound){
- throw new UtilsException("("+principal+") Non possono coesistere i separatore \",\" e \"/\", solo uno dei due tipi deve essere utilizzato come delimitatore (usare eventualmente come carattere di escape '\\')");
- }
- if(!commaFound && !slashFound && !principal.contains("=")){
- throw new UtilsException("("+principal+") "+type+" non valido, nemmeno una coppia nome=valore trovata");
- }
- String [] valoriPrincipal = CertificateUtils.getValoriPrincipal(principal, type);
- validaPrincipal(valoriPrincipal, principal, type);
-
- if(normalizedException!=null){
- throw normalizedException;
- }
- }
- private static void validaPrincipal(String [] valoriPrincipal, String principal, PrincipalType type) throws UtilsException {
- boolean campoObbligatorioCN = false;
- boolean campoObbligatorioOU = false;
- boolean campoObbligatorioO = false;
- boolean campoObbligatorioL = false;
- boolean campoObbligatorioST = false;
- boolean campoObbligatorioC = false;
- boolean campoObbligatorioE = false;
- for(int i=0; i<valoriPrincipal.length; i++){
-
- String [] keyValue = getKeyValuePairEngine(valoriPrincipal[i], principal, type);
- if(keyValue[0].trim().contains(" ")){
- throw new UtilsException(getAnalisiTypePrefixString(principal, type)+"fallita: il campo ["+valoriPrincipal[i]+"] contiene spazi nella chiave identificativa ["+keyValue[0].trim()+"]");
- }
-
- if(CertificateUtils.formatKeyPrincipal(keyValue[0]).equalsIgnoreCase("CN")){
- campoObbligatorioCN = true;
- }
- else if(CertificateUtils.formatKeyPrincipal(keyValue[0]).equalsIgnoreCase("OU")){
- campoObbligatorioOU = true;
- }
- else if(CertificateUtils.formatKeyPrincipal(keyValue[0]).equalsIgnoreCase("O")){
- campoObbligatorioO = true;
- }
- else if(CertificateUtils.formatKeyPrincipal(keyValue[0]).equalsIgnoreCase("L")){
- campoObbligatorioL = true;
- }
- else if(CertificateUtils.formatKeyPrincipal(keyValue[0]).equalsIgnoreCase("ST")){
- campoObbligatorioST = true;
- }
- else if(CertificateUtils.formatKeyPrincipal(keyValue[0]).equalsIgnoreCase("C")){
- campoObbligatorioC = true;
- }
- else if(CertificateUtils.formatKeyPrincipal(keyValue[0]).equalsIgnoreCase("E")){
- campoObbligatorioE = true;
- }
- }
- if(!campoObbligatorioCN && !campoObbligatorioOU && !campoObbligatorioO && !campoObbligatorioL && !campoObbligatorioST && !campoObbligatorioC && !campoObbligatorioE){
- throw new UtilsException("("+principal+") Almeno un attributo di certificato tra 'CN', 'OU', 'O', 'L', 'ST', 'C' e 'E' deve essere valorizzato.");
- }
- }
-
- public static String normalizePrincipal(String principalParam) throws UtilsException{
-
- /*
- * The principal extract from class represents an X.500 Principal.
- * X500Principals are represented by distinguished names such as "CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US".
- * This class can be instantiated by using a string representation of the distinguished name, or by using the ASN.1 DER encoded byte representation
- * of the distinguished name.
- * The current specification for the string representation of a distinguished name is defined in RFC 2253:
- * Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names.
- * This class, however, accepts string formats from both RFC 2253 and RFC 1779: A String Representation of Distinguished Names,
- * and also recognizes attribute type keywords whose OIDs (Object Identifiers) are defined in RFC 3280:
- * Internet X.509 Public Key Infrastructure Certificate and CRL Profile.
- */
-
- try{
- // Normalizza da un eventuale formato human readable o da un formato RFC 1779 nel formato RFC 2253 gestito poi nel seguito del codice.
- // Alcuni esempi dove il carattere '/' viene usato internamente come valore del CN
- // Esempio di formato "human readable": /C=IT/ST=Italiy/OU=PROVA di Bari, di Como/CN=SPC/SOGGETTO
- // Esempio di formato "RFC 1779": CN=SPC/SOGGETTO, OU="PROVA di Bari, di Como", ST=Italiy, C=IT
- // Esempio di formato "RFC 2253": CN=SPC/SOGGETTO,OU=PROVA di Bari\, di Como,ST=Italiy,C=IT
- return RFC2253Parser.normalize(principalParam);
- /**String principal = RFC2253Parser.normalize(principalParam);
- System.out.println(" ORIGINALE ["+principalParam+"] NORMALIZZATO ["+principal+"]");
- return principal;*/
- }catch(Exception e){
- throw new UtilsException("("+principalParam+") Normalizzazione RFC2253 non riuscita: "+e.getMessage(),e);
- }
- }
- public static String [] getValoriPrincipal(String principalParam, PrincipalType type) throws UtilsException{
- try{
- /** System.out.println("PRINCIPAL getValoriPrincipal["+principalParam+"]"); */
- String principal = normalizePrincipal(principalParam);
- /** System.out.println("PRINCIPAL dopo normalize getValoriPrincipal["+principal+"]"); */
-
- return getValoriPrincipalEngine(principal, type);
-
- }catch(Exception e){
-
- /** System.out.println("PRINCIPAL getValoriPrincipal["+principalParam+"] errore: "+e.getMessage()); */
-
- try{
-
- javax.naming.ldap.LdapName prova = new javax.naming.ldap.LdapName(principalParam);
- Enumeration<String> ens = prova.getAll();
- List<String> values = new ArrayList<>();
- while (ens.hasMoreElements()) {
- String name = ens.nextElement();
- values.add(name);
- }
-
- if(!values.isEmpty()){
- return values.toArray(new String[1]);
- }
- else{
- throw new UtilsException("Coppie nome/valore non trovate");
- }
-
- }catch(Exception e2Level){
- /**e2Level.printStackTrace(System.out); */
- throw new UtilsException("("+principalParam+") javax.naming.ldap.LdapName reader failed: "+e2Level.getMessage()+". \nFirst method error: "+e.getMessage(),e);
- }
-
- }
- }
-
- private static String [] getValoriPrincipalEngine(String principal, PrincipalType type) throws UtilsException{
-
- String [] valori;
- boolean commaFound = contains(principal, ",");
- boolean slashFound = contains(principal, "/");
- /**System.out.println("PRINCIPAL _getValoriPrincipal commaFound["+commaFound+"] slashFound["+slashFound+"]"); */
- if(commaFound){
- if(principal.startsWith(",")){
- principal = principal.substring(1);
- }
- if(principal.endsWith(",")){
- principal = principal.substring(0,principal.length()-1);
- }
- /**System.out.println("PRINCIPAL _getValoriPrincipal preSplit , ["+principal+"] ..");*/
- valori = Utilities.split(principal, ',');
- }else{
- valori = getValoriPrincipalEngine(principal, type, slashFound);
- }
- if(valori==null || valori.length<1){
- throw new UtilsException(getAnalisiTypePrefixString(principal, type)+"interno alla configurazione di OpenSPCoop non riuscita: null??");
- }
-
- // validazione
- for(int i=0; i<valori.length; i++){
- getKeyValuePairEngine(valori[i], principal, type);
- }
-
- return valori;
- }
- private static String [] getValoriPrincipalEngine(String principal, PrincipalType type, boolean slashFound) throws UtilsException {
- /**System.out.println("PRINCIPAL _getValoriPrincipal comma not found ["+principal+"] .."); */
- String [] valori = null;
- if(!slashFound){
- /** System.out.println("PRINCIPAL _getValoriPrincipal slash not found ["+principal+"] .."); */
- int indexOf = principal.indexOf("=");
- if(indexOf<=0){
- throw new UtilsException("("+principal+") Separatore validi per il "+type+" interno alla configurazione di OpenSPCoop non trovati: \",\" o \"/\" e carattere \"=\" non presente");
- }
- if(principal.indexOf("=",indexOf+1)>=0){
- throw new UtilsException("("+principal+") Separatore validi per il "+type+" interno alla configurazione di OpenSPCoop non trovati: \",\" o \"/\"");
- }
- valori = new String[1];
- valori[0] = principal;
- }else{
- valori = getValoriSlashPrincipalEngine(principal);
- }
- return valori;
- }
- private static String [] getValoriSlashPrincipalEngine(String principal) throws UtilsException {
- if(principal.startsWith("/")){
- principal = principal.substring(1);
- }
- if(principal.endsWith("/")){
- principal = principal.substring(0,principal.length()-1);
- }
- /**System.out.println("PRINCIPAL _getValoriPrincipal preSplit / ["+principal+"] .."); */
- String [] tmpValori = Utilities.split(principal, '/');
-
- // Bug Fix OP-670 certificato formato come:
- // C=IT/ST= /O=Esempio di Agenzia/OU=Servizi Informatici/CN=Ministero dell'Interno/prova/23234234554/DEMO
- List<String> normalize = new ArrayList<>();
- StringBuilder bf = new StringBuilder();
- for (String tmp : tmpValori) {
- if(tmp.contains("=")) {
- if(bf.length()>0) {
- normalize.add(bf.toString());
- bf.delete(0, bf.length());
- }
- bf.append(tmp);
- }
- else {
- bf.append("/").append(tmp);
- }
- }
- if(bf.length()>0) {
- normalize.add(bf.toString());
- bf.delete(0, bf.length());
- }
- return normalize.toArray(new String[1]);
- }
-
- public static Map<String, List<String>> getPrincipalIntoMap(String principal, PrincipalType type) throws UtilsException{
- Map<String, List<String>> hashPrincipal = new HashMap<>();
- String [] valoriPrincipal = CertificateUtils.getValoriPrincipal(principal, type);
- for(int i=0; i<valoriPrincipal.length; i++){
-
- // override eccezione in caso '=' non rpesente
- if(!valoriPrincipal[i].contains("=")){
- String fallita = "fallita"+": ["+valoriPrincipal[i]+"] ";
- throw new UtilsException(getAnalisiTypePrefixString(principal, type)+fallita+"non separata dal carattere \"=\"");
- }
- String [] keyValue = getKeyValuePairEngine(valoriPrincipal[i], principal, type);
-
- /**System.out.println("CONF INTERNA ["+Utilities.formatKeyPrincipal(keyValue[0])+"] ["+Utilities.formatValuePrincipal(keyValue[1])+"]");*/
- String formatKey = CertificateUtils.formatKeyPrincipal(keyValue[0]);
- String formatValue = CertificateUtils.formatValuePrincipal(keyValue[1]);
- List<String> listValue = null;
- if(hashPrincipal.containsKey(formatKey)) {
- listValue = hashPrincipal.get(formatKey);
- }
- else {
- listValue = new ArrayList<>();
- hashPrincipal.put(formatKey, listValue);
- }
- listValue.add(formatValue);
- }
- return hashPrincipal;
- }
- public static String formatKeyPrincipal(String keyPrincipal){
- return keyPrincipal.trim().toLowerCase();
- }
- public static String formatValuePrincipal(String valuePrincipal){
- // siccome uso il carattere '/' come separatore, un eventuale '/' deve essere escaped.
- StringBuilder bf = new StringBuilder();
- for (int i = 0; i < valuePrincipal.length(); i++) {
- if(valuePrincipal.charAt(i)=='/'){
- // escape
- if(i==0){
- bf.append('\\');
- }
- else{
- // verifico se non ho gia' effettuato l'escape
- if(valuePrincipal.charAt((i-1))!='\\'){
- bf.append('\\');
- }
- }
- }
- bf.append(valuePrincipal.charAt(i));
- }
- String value = bf.toString();
- if(TRIM_VALUE_BEFORE_SAVE_DB) {
- value = value.trim();
- }
- return value;
- }
- private static String[] getKeyValuePairEngine(String keyValue, String principal, PrincipalType type) throws UtilsException {
-
- if(!keyValue.contains("=")){
- throw new UtilsException(getAnalisiTypePrefixString(principal, type)+"fallita: ["+keyValue+"] non separata dal carattere \"=\". Verificare che non esistano coppie che possiedono valori che contengono il carattere separatore (usare eventualmente come carattere di escape '\\')");
- }
-
- // Bug Fix OP-664
- // Per non bruciare gli spazi presenti nei valori della chiave che sono ammessi. Ad esempio e' capitato un "C=IT,ST= ,CN=XXESEMPIOXX"
- /**String [] keyValue = keyValue.trim().split("=");*/
- String [] keyValueReturn = keyValue.split("="); // lo spazio รจ ammesso nel valore.
- if(keyValueReturn.length<2){
- if(TRIM_VALUE_BEFORE_SAVE_DB && keyValueReturn.length==1) {
- // Serve per i valori inseriti che poi vengono comunque normalizzati con il trim. Se il valore era ' ' viene normalizzato a ''
- // una volta riletto poi si ottiene l'errore.
- // Che ci sia l'uguale e' garantito dai controlli sopra. In pratica keyValue.endsWith("=")
- String key = keyValueReturn[0];
- keyValueReturn = new String[2];
- keyValueReturn[0] = key;
- keyValueReturn[1] = "";
- }
- else {
- throw new UtilsException(getAnalisiTypePrefixString(principal, type)+"fallita: ["+keyValue+"] non contiene un valore? Verificare che non esistano coppie che possiedono valori che contengono il carattere separatore (usare eventualmente come carattere di escape '\\')");
- }
- }
-
- // Lo spazio e' ammesso nel valore, ma non nella chiave
- keyValueReturn[0] = keyValueReturn[0].trim();
- /**System.out.println("KEY["+keyValueReturn[0]+"]=VALUE["+keyValueReturn[1]+"]");*/
-
- // Questo controllo non deve essere fatto poiche' il valore puo' contenere il '='.
- /** if(keyValue.length!=2){
- // throw new UtilsException(getAnalisiTypePrefixString(principal, type)+"fallita: ["+keyValue+"] contiene piu' di un carattere \"=\"");
- // }*/
- if(keyValueReturn.length==2) {
- return keyValueReturn;
- }
- else {
- String[] keyValueReturnNormalized = new String[2];
- keyValueReturnNormalized[0] = keyValueReturn[0];
- keyValueReturnNormalized[1] = extractValueFromKeyPairEngine(keyValue);
- return keyValueReturnNormalized;
- }
-
- }
- private static String extractValueFromKeyPairEngine(String keyValue) throws UtilsException {
- // Questo metodo server poiche' il valore puo' contenere il '=' ed il carattere ' ' anche all'inizio o alla fine.
- // Quindi uno split con il carattere '=' non puo' essere usato.
- // Deve quindi essere estratto dopo il primo uguale
- int indexOf = keyValue.indexOf("=");
- if(indexOf<=0) {
- throw new UtilsException("Carattere '=' non presente in ["+keyValue+"]");
- }
- return keyValue.substring(indexOf+1);
- /**String valoreEstratto = keyValue.substring(indexOf+1);
- System.out.println("VALORE ESTRATTO ["+valoreEstratto+"]");
- return valoreEstratto;*/
- }
-
-
- private static boolean contains(String value,String separator){
- int indexOf = value.indexOf(separator);
- boolean found = false;
- if(indexOf==0){
- found = true;
- }
- else{
- boolean itera = true;
- while(indexOf>0 && itera){
- char precedente = value.charAt(indexOf-1);
- if(precedente == '\\'){
- if(indexOf+1>value.length()){
- itera=false;
- }
- else{
- indexOf = value.indexOf(separator,indexOf+1);
- }
- }
- else{
- found = true;
- itera=false;
- }
- }
- }
- return found;
- }
-
- public static Certificate readCertificate(CertificateDecodeConfig config, String certificateParam) throws UtilsException {
- return readCertificateEngine(config, certificateParam, Charset.UTF_8.getValue());
- }
- public static Certificate readCertificate(CertificateDecodeConfig config, String certificateParam, String charset) throws UtilsException {
- return readCertificateEngine(config, certificateParam, charset);
- }
-
- private static Certificate readCertificateEngine(CertificateDecodeConfig config, String certificateParam, String charset) throws UtilsException {
- if(config.isUrlDecodeOrBase64Decode() || config.isUrlDecodeOrBase64DecodeOrHexDecode()) {
-
- Throwable tUrlDecode = null;
- try {
- config.setUrlDecode(true);
- config.setBase64Decode(false);
- config.setHexDecode(false);
- return readCertificateEngineByConfig(config, certificateParam, charset);
- }catch(Exception t) {
- tUrlDecode = t;
- }
-
- Throwable tBase64Decode = null;
- try {
- config.setUrlDecode(false);
- config.setBase64Decode(true);
- config.setHexDecode(false);
- return readCertificateEngineByConfig(config, certificateParam, charset);
- }catch(Exception t) {
- tBase64Decode = t;
- }
-
- Throwable tHexDecode = null;
- if(config.isUrlDecodeOrBase64DecodeOrHexDecode()) {
- try {
- config.setUrlDecode(false);
- config.setBase64Decode(false);
- config.setHexDecode(true);
- return readCertificateEngineByConfig(config, certificateParam, charset);
- }catch(Exception t) {
- tHexDecode = t;
- }
- }
-
- UtilsMultiException uMulti = config.isUrlDecodeOrBase64DecodeOrHexDecode() ?
- new UtilsMultiException("Decodifica non riuscita", tUrlDecode, tBase64Decode, tHexDecode)
- :
- new UtilsMultiException("Decodifica non riuscita", tUrlDecode, tBase64Decode);
- throw new UtilsException(uMulti.getMessage(),uMulti);
- }
- else {
- return readCertificateEngineByConfig(config, certificateParam, charset);
- }
- }
- private static Certificate readCertificateEngineByConfig(CertificateDecodeConfig config, String certificateParam, String charset) throws UtilsException {
-
- if(certificateParam==null || "".equals(certificateParam)){
- throw new UtilsException("Certificate non fornito");
- }
-
- try {
-
- String certificate = certificateParam;
-
- if(config.isUrlDecode()) {
- certificate = UriUtils.decode(certificate, charset);
- }
-
- boolean forceEnrichPEMBeginEnd = false;
- if(config.isReplace()) {
- StringBuilder sbNewCertificate = new StringBuilder();
- forceEnrichPEMBeginEnd = replaceCharacters(config, certificate, sbNewCertificate);
- certificate = sbNewCertificate.toString();
- }
-
- if(config.isEnrichPEMBeginEnd() || forceEnrichPEMBeginEnd) {
- certificate = addPEMDeclaration(certificate, forceEnrichPEMBeginEnd);
- }
-
- byte [] certBytes = null;
- if(config.isBase64Decode()) {
- certBytes = Base64Utilities.decode(certificate);
- }
- else if(config.isHexDecode()) {
- certBytes = HexBinaryUtilities.decode(certificate);
- }
- else {
- certBytes = certificate.getBytes(charset);
- }
-
- // Per adesso l'utility di load gestisce solo il tipo DER. La decodifica in base64 รจ quindi essenziale, a meno che non sia un DER.
-
- return ArchiveLoader.load(certBytes);
-
- }catch(Exception e) {
- throw new UtilsException(e.getMessage(), e);
- }
-
- }
-
- private static boolean replaceCharacters(CertificateDecodeConfig config, String certificate, StringBuilder sbNewCertificate) {
- boolean forceEnrichPEMBeginEnd = false;
- // per evitare di sovrascrivere 'BEGIN' e 'END'
- if(certificate.startsWith(PEMReader.X509_BEGIN) && certificate.length()>PEMReader.X509_BEGIN.length()) {
- certificate = certificate.substring(PEMReader.X509_BEGIN.length());
- forceEnrichPEMBeginEnd = true;
- }
- if(certificate.endsWith(PEMReader.X509_END) && certificate.length()>PEMReader.X509_END.length()) {
- certificate = certificate.substring(0, certificate.length()-PEMReader.X509_END.length());
- }
-
- int index = 0; // per evitare bug di cicli infiniti
- while(certificate.contains(config.getReplaceSource()) && index<10000) {
- certificate = certificate.replace(config.getReplaceSource(), config.getReplaceDest());
- index++;
- }
- sbNewCertificate.append(certificate);
- return forceEnrichPEMBeginEnd;
- }
-
- private static String addPEMDeclaration(String certificate, boolean forceEnrichPEMBeginEnd) {
- if(!certificate.startsWith(PEMReader.X509_BEGIN)) {
- certificate = PEMReader.X509_BEGIN+ (forceEnrichPEMBeginEnd?"":"\n")+ certificate;
- }
- if(!certificate.endsWith(PEMReader.X509_END)) {
- certificate = certificate+ (forceEnrichPEMBeginEnd?"":"\n") +PEMReader.X509_END;
- }
- return certificate;
- }
-
- public static String toPEM(java.security.cert.X509Certificate cert) throws UtilsException {
- try {
- java.io.StringWriter sw = new java.io.StringWriter();
- try (org.bouncycastle.openssl.jcajce.JcaPEMWriter pw = new org.bouncycastle.openssl.jcajce.JcaPEMWriter(sw)) {
- pw.writeObject(cert);
- }
- sw.flush();
- sw.close();
- return sw.toString();
- }catch(Exception e) {
- throw new UtilsException(e.getMessage(), e);
- }
- }
- public static String toPEM(PrivateKey privateKey) throws UtilsException {
- try {
- java.io.StringWriter sw = new java.io.StringWriter();
- try (org.bouncycastle.openssl.jcajce.JcaPEMWriter pw = new org.bouncycastle.openssl.jcajce.JcaPEMWriter(sw)) {
- pw.writeObject(privateKey);
- }
- sw.flush();
- sw.close();
- return sw.toString();
- }catch(Exception e) {
- throw new UtilsException(e.getMessage(), e);
- }
- }
- }