JsonVerifySignature.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.security;

  21. import java.io.File;
  22. import java.security.PublicKey;
  23. import java.security.cert.CertStore;
  24. import java.security.cert.Certificate;
  25. import java.security.cert.X509Certificate;
  26. import java.util.List;
  27. import java.util.Properties;

  28. import org.apache.cxf.common.util.Base64UrlUtility;
  29. import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
  30. import org.apache.cxf.rs.security.jose.jwk.JsonWebKeys;
  31. import org.apache.cxf.rs.security.jose.jwk.JwkUtils;
  32. import org.apache.cxf.rs.security.jose.jws.JwsCompactConsumer;
  33. import org.apache.cxf.rs.security.jose.jws.JwsHeaders;
  34. import org.apache.cxf.rs.security.jose.jws.JwsJsonConsumer;
  35. import org.apache.cxf.rs.security.jose.jws.JwsJsonProducer;
  36. import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
  37. import org.apache.cxf.rs.security.jose.jws.JwsUtils;
  38. import org.apache.cxf.rt.security.rs.RSSecurityConstants;
  39. import org.openspcoop2.utils.UtilsException;
  40. import org.openspcoop2.utils.certificate.ArchiveLoader;
  41. import org.openspcoop2.utils.certificate.CertificateInfo;
  42. import org.openspcoop2.utils.certificate.JWK;
  43. import org.openspcoop2.utils.certificate.JWKSet;
  44. import org.openspcoop2.utils.certificate.KeyStore;
  45. import org.openspcoop2.utils.certificate.remote.IRemoteStoreProvider;
  46. import org.openspcoop2.utils.certificate.remote.RemoteKeyType;
  47. import org.openspcoop2.utils.certificate.remote.RemoteStoreConfig;
  48. import org.openspcoop2.utils.io.Base64Utilities;
  49. import org.openspcoop2.utils.transport.http.HttpResponse;
  50. import org.openspcoop2.utils.transport.http.HttpUtilities;
  51. import org.openspcoop2.utils.transport.http.IOCSPValidator;

  52. /**
  53.  * JsonVerifySignature
  54.  *
  55.  * @author Poli Andrea (apoli@link.it)
  56.  * @author $Author$
  57.  * @version $Rev$, $Date$
  58.  */
  59. public class JsonVerifySignature {

  60.     private JwsSignatureVerifier provider;
  61.     private Properties propsConfig;
  62.     private JWTOptions options;
  63.     private Properties properties;
  64.     private boolean dynamicProvider;
  65.    
  66.     private JwsHeaders jwsDecodedHeaders;
  67.     private String decodedHeader;
  68.    
  69.     private String decodedPayload;
  70.     private byte[] decodedPayloadAsByte;
  71.    
  72.     private KeyStore trustStoreCertificatiX509; // per verificare i certificati presenti nell'header
  73.     public KeyStore getTrustStoreCertificatiX509() {
  74.         return this.trustStoreCertificatiX509;
  75.     }
  76.     private JsonWebKeys jsonWebKeys; // dove prendere il certificato per validare rispetto al kid
  77.    
  78.     private IRemoteStoreProvider remoteStoreProvider; // dove prendere il certificato remoto per validare rispetto al kid
  79.     private RemoteKeyType remoteStoreKeyType;
  80.     private RemoteStoreConfig remoteStoreConfig;
  81.    
  82.     private KeyStore trustStoreHttps; // per accedere ad un endpoint https dove scaricare i certificati
  83.     public KeyStore getTrustStoreHttps() {
  84.         return this.trustStoreHttps;
  85.     }
  86.     private CertStore crlHttps; // per verificare i certificati http server rispetto alle crl
  87.     public void setCrlHttps(CertStore crlHttps) {
  88.         this.crlHttps = crlHttps;
  89.     }
  90.     private IOCSPValidator ocspValidatorHttps; // per verificare i certificati http server rispetto a servizi OCSP
  91.     public void setOcspValidatorHttps(IOCSPValidator ocspValidator) {
  92.         this.ocspValidatorHttps = ocspValidator;
  93.     }
  94.    
  95.     private CertStore crlX509; // per verificare i certificati rispetto alle crl
  96.     public void setCrlX509(CertStore crlX509) {
  97.         this.crlX509 = crlX509;
  98.     }
  99.     private IOCSPValidator ocspValidatorX509; // per verificare i certificati rispetto a servizi OCSP
  100.     public void setOcspValidatorX509(IOCSPValidator ocspValidator) {
  101.         this.ocspValidatorX509 = ocspValidator;
  102.     }

  103.     private CertificateValidityCheck validityCheck = CertificateValidityCheck.ENABLED; // validazione (date) del certificato utilizzato per firmare il token    
  104.     public void setValidityCheck(CertificateValidityCheck validityCheck) {
  105.         this.validityCheck = validityCheck;
  106.     }
  107.    
  108.     private boolean jksPasswordRequired=true;
  109.     private boolean pkcs12PasswordRequired=true;
  110.     public void setJksPasswordRequired(boolean jksPasswordRequired) {
  111.         this.jksPasswordRequired = jksPasswordRequired;
  112.     }
  113.     public void setPkcs12PasswordRequired(boolean pkcs12PasswordRequired) {
  114.         this.pkcs12PasswordRequired = pkcs12PasswordRequired;
  115.     }  

  116.     public JsonVerifySignature(Properties props, JWTOptions options) throws UtilsException{
  117.         try {
  118.             this.propsConfig = props;
  119.             this.dynamicProvider = JsonUtils.isDynamicProvider(props); // rimuove l'alias
  120.             if(this.dynamicProvider) {
  121.                 this.properties = props;
  122.             }
  123.             else {
  124.                 this.provider = loadProviderFromProperties(props, null); // nel caso di jceks deve essere definito l'algoritmo se non e' dinamico
  125.             }
  126.             this.options = options;
  127.         }catch(Exception t) {
  128.             throw JsonUtils.convert(options.getSerialization(), JsonUtils.SIGNATURE,JsonUtils.RECEIVER,t);
  129.         }
  130.     }

  131.     private JwsSignatureVerifier loadProviderFromProperties(Properties props, org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm signatureAlgorithm) throws UtilsException {
  132.         File fTmp = null;
  133.         try {
  134.             fTmp = JsonUtils.normalizeProperties(props); // in caso di url http viene letta la risorsa remota e salvata in tmp
  135.             /**java.util.Enumeration<?> en = props.keys();
  136.             while (en.hasMoreElements()) {
  137.                 String key = (String) en.nextElement();
  138.                 System.out.println("- ["+key+"] ["+props.getProperty(key)+"]");
  139.             }*/
  140.            
  141.             JwsSignatureVerifier providerReturn = null;
  142.             if(signatureAlgorithm!=null) {
  143.                 providerReturn = JsonUtils.getJwsSignatureVerifier(props, signatureAlgorithm);
  144.             }
  145.             else {
  146.                 providerReturn = JsonUtils.getJwsSignatureVerifier(props);
  147.             }
  148.             if(providerReturn==null) {
  149.                 providerReturn = JwsUtils.loadSignatureVerifier(JsonUtils.newMessage(), props, new JwsHeaders());
  150.             }
  151.             if(providerReturn==null) {
  152.                 throw new UtilsException("JwsSignatureVerifier provider not found");
  153.             }
  154.             return providerReturn;
  155.         }finally {
  156.             try {
  157.                 if(fTmp!=null) {
  158.                     java.nio.file.Files.delete(fTmp.toPath());
  159.                 }
  160.             }catch(Exception t) {
  161.                 // ignore
  162.             }
  163.         }
  164.     }
  165.    
  166.     public JsonVerifySignature(java.security.KeyStore keystore, String alias, String signatureAlgorithm, JWTOptions options) throws UtilsException{
  167.         this(new KeyStore(keystore), alias, signatureAlgorithm, options);
  168.     }
  169.     public JsonVerifySignature(KeyStore keystore, String alias, String signatureAlgorithm, JWTOptions options) throws UtilsException{
  170.         try {
  171.             org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm algo = org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm.getAlgorithm(signatureAlgorithm);
  172.             this.provider = JwsUtils.getPublicKeySignatureVerifier((X509Certificate) keystore.getCertificate(alias), algo);
  173.             this.options=options;
  174.            
  175.             this.trustStoreCertificatiX509 = keystore; // per abilitare la validazione crl o ocsp
  176.            
  177.         }catch(Exception t) {
  178.             throw JsonUtils.convert(options.getSerialization(), JsonUtils.SIGNATURE,JsonUtils.RECEIVER,t);
  179.         }
  180.     }
  181.    
  182.     public JsonVerifySignature(java.security.KeyStore keystore, String alias, String passwordPrivateKey, String signatureAlgorithm, JWTOptions options) throws UtilsException{
  183.         this(new KeyStore(keystore), alias, passwordPrivateKey, signatureAlgorithm, options);
  184.     }
  185.     public JsonVerifySignature(KeyStore keystore, String alias, String passwordPrivateKey, String signatureAlgorithm, JWTOptions options) throws UtilsException{
  186.         try {
  187.             org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm algo = org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm.getAlgorithm(signatureAlgorithm);
  188.             this.provider = JwsUtils.getHmacSignatureVerifier(keystore.getSecretKey(alias, passwordPrivateKey).getEncoded(), algo);
  189.             if(this.provider==null) {
  190.                 throw new UtilsException("(JCEKS) JwsSignatureVerifier init failed; check signature algorithm ("+signatureAlgorithm+")");
  191.             }
  192.             this.options=options;
  193.            
  194.             this.trustStoreCertificatiX509 = keystore; // per abilitare la validazione crl o ocsp
  195.            
  196.         }catch(Exception t) {
  197.             throw JsonUtils.convert(options.getSerialization(), JsonUtils.SIGNATURE,JsonUtils.RECEIVER,t);
  198.         }
  199.     }
  200.    
  201.     public JsonVerifySignature(JsonWebKeys jsonWebKeys, boolean secretKey, String alias, String signatureAlgorithm, JWTOptions options) throws UtilsException{
  202.         this(JsonUtils.readKey(jsonWebKeys, alias), secretKey, signatureAlgorithm, options);
  203.     }  
  204.     public JsonVerifySignature(JsonWebKey jsonWebKey, boolean secretKey, String signatureAlgorithm, JWTOptions options) throws UtilsException{
  205.         try {
  206.             org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm algo = org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm.getAlgorithm(signatureAlgorithm);
  207.             if(secretKey) {
  208.                 this.provider = JwsUtils.getSignatureVerifier(jsonWebKey, algo);
  209.                 if(this.provider==null) {
  210.                     throw new UtilsException("(JsonWebKey) JwsSignatureVerifier init failed; check signature algorithm ("+signatureAlgorithm+")");
  211.                 }
  212.             }
  213.             else {
  214.                 this.provider = JwsUtils.getPublicKeySignatureVerifier(JwkUtils.toRSAPublicKey(jsonWebKey), algo);
  215.             }
  216.             this.options=options;
  217.         }catch(Exception t) {
  218.             throw JsonUtils.convert(options.getSerialization(), JsonUtils.SIGNATURE,JsonUtils.RECEIVER,t);
  219.         }
  220.     }
  221.    
  222.     public JsonVerifySignature(String secret, String signatureAlgorithm, JWTOptions options) throws UtilsException{
  223.         try {
  224.             org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm algo = org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm.getAlgorithm(signatureAlgorithm);
  225.             this.provider = JwsUtils.getHmacSignatureVerifier(secret.getBytes(), algo);
  226.             if(this.provider==null) {
  227.                 throw new UtilsException("(Secret) JwsSignatureVerifier init failed; check signature algorithm ("+signatureAlgorithm+")");
  228.             }
  229.             this.options=options;
  230.         }catch(Exception t) {
  231.             throw JsonUtils.convert(options.getSerialization(), JsonUtils.SIGNATURE,JsonUtils.RECEIVER,t);
  232.         }
  233.     }
  234.    
  235.    
  236.     public JsonVerifySignature(JWTOptions options) {
  237.         initVerifyCertificatiHeaderJWTEngine(null, null,
  238.                 null, options);
  239.     }
  240.     public JsonVerifySignature(Properties propsTrustStoreHttps, java.security.KeyStore trustStoreVerificaCertificato, JWTOptions options) {
  241.         initVerifyCertificatiHeaderJWTEngine(propsTrustStoreHttps, null,
  242.                 new KeyStore(trustStoreVerificaCertificato), options);
  243.     }
  244.     public JsonVerifySignature(Properties propsTrustStoreHttps, KeyStore trustStore, JWTOptions options){
  245.         initVerifyCertificatiHeaderJWTEngine(propsTrustStoreHttps, null,
  246.                 trustStore, options);
  247.     }
  248.     public JsonVerifySignature(java.security.KeyStore trustStoreHttps, java.security.KeyStore trustStoreVerificaCertificato, JWTOptions options) {
  249.         initVerifyCertificatiHeaderJWTEngine(null, new KeyStore(trustStoreHttps),
  250.                 new KeyStore(trustStoreVerificaCertificato), options);
  251.     }
  252.     public JsonVerifySignature(KeyStore trustStoreHttps, KeyStore trustStore, JWTOptions options) {
  253.         initVerifyCertificatiHeaderJWTEngine(null, trustStoreHttps,
  254.                 trustStore, options);
  255.     }
  256.     public JsonVerifySignature(java.security.KeyStore trustStoreVerificaCertificato, JWTOptions options) {
  257.         initVerifyCertificatiHeaderJWTEngine(null, null,
  258.                 new KeyStore(trustStoreVerificaCertificato), options);
  259.     }
  260.     public JsonVerifySignature(KeyStore trustStore, JWTOptions options) {
  261.         initVerifyCertificatiHeaderJWTEngine(null, null,
  262.                 trustStore, options);
  263.     }
  264.     private void initVerifyCertificatiHeaderJWTEngine(Properties propsTrustStoreHttps, KeyStore trustStoreHttps,
  265.             KeyStore trustStoreVerificaCertificato, JWTOptions options) {
  266.         // verra usato l'header per validare ed ottenere il certificato
  267.         this.options=options;
  268.         this.properties = propsTrustStoreHttps; // le proprieta' servono per risolvere le url https
  269.         this.trustStoreHttps = trustStoreHttps;
  270.         this.trustStoreCertificatiX509 = trustStoreVerificaCertificato;
  271.     }
  272.    
  273.     public JsonVerifySignature(JsonWebKeys jsonWebKeys, JWTOptions options) {
  274.         initVerifyCertificatiHeaderJWTEngine(jsonWebKeys, options);
  275.     }
  276.     private void initVerifyCertificatiHeaderJWTEngine(JsonWebKeys jsonWebKeys, JWTOptions options) {
  277.         // verra usato l'header per validare ed ottenere il certificato
  278.         this.options=options;
  279.         this.jsonWebKeys = jsonWebKeys;
  280.     }

  281.    
  282.     public JsonVerifySignature(IRemoteStoreProvider remoteStoreProvider, RemoteKeyType remoteStoreKeyType, RemoteStoreConfig remoteStoreConfig, JWTOptions options) {
  283.         initVerifyCertificatiHeaderRemoteStoreEngine(remoteStoreProvider, remoteStoreKeyType, remoteStoreConfig, options);
  284.     }
  285.     private void initVerifyCertificatiHeaderRemoteStoreEngine(IRemoteStoreProvider remoteStoreProvider, RemoteKeyType remoteStoreKeyType, RemoteStoreConfig remoteStoreConfig, JWTOptions options) {
  286.         // verra usato l'header per validare ed ottenere il certificato
  287.         this.options=options;
  288.         this.remoteStoreProvider = remoteStoreProvider;
  289.         this.remoteStoreKeyType = remoteStoreKeyType;
  290.         this.remoteStoreConfig = remoteStoreConfig;
  291.     }
  292.    

  293.     public boolean verify(String jsonString) throws UtilsException{
  294.         try {
  295.             switch(this.options.getSerialization()) {
  296.                 case JSON: return verifyJson(jsonString);
  297.                 case COMPACT: return verifyCompact(jsonString);
  298.                 default: throw new UtilsException("Unsupported serialization '"+this.options.getSerialization()+"'");
  299.             }
  300.         }
  301.         catch(Exception t) {
  302.             throw JsonUtils.convert(this.options.getSerialization(), JsonUtils.SIGNATURE,JsonUtils.RECEIVER,t);
  303.         }
  304.     }

  305.     public boolean verifyDetached(String jsonDetachedSignature, String jsonDetachedPayload) throws UtilsException{
  306.         try {
  307.             switch(this.options.getSerialization()) {
  308.                 case JSON: return verifyDetachedJson(jsonDetachedSignature, jsonDetachedPayload);
  309.                 case COMPACT: return verifyDetachedCompact(jsonDetachedSignature, jsonDetachedPayload);
  310.                 default: throw new UtilsException("Unsupported serialization '"+this.options.getSerialization()+"'");
  311.             }
  312.         }
  313.         catch(Exception t) {
  314.             throw JsonUtils.convert(this.options.getSerialization(), JsonUtils.SIGNATURE,JsonUtils.RECEIVER,t);
  315.         }
  316.     }

  317.     private boolean verifyDetachedJson(String jsonDetachedSignature, String jsonDetachedPayload) throws UtilsException {
  318.         JwsJsonProducer producer = new JwsJsonProducer(jsonDetachedPayload);
  319.         JwsJsonConsumer consumer = new JwsJsonConsumer(jsonDetachedSignature, producer.getUnsignedEncodedPayload());
  320.         return this.verifyJsonEngine(consumer);
  321.     }
  322.     private boolean verifyJson(String jsonString) throws UtilsException {
  323.         JwsJsonConsumer consumer = new JwsJsonConsumer(jsonString);
  324.         return this.verifyJsonEngine(consumer);
  325.     }  
  326.     private boolean verifyJsonEngine(JwsJsonConsumer consumer) throws UtilsException {
  327.        
  328.         JwsHeaders jwsHeaders = null;
  329.         if(consumer.getSignatureEntries()!=null && !consumer.getSignatureEntries().isEmpty() &&
  330.             // prendo la prima entry
  331.             consumer.getSignatureEntries().get(0)!=null
  332.             ) {
  333.             jwsHeaders = consumer.getSignatureEntries().get(0).getProtectedHeader();
  334.         }
  335.         JwsSignatureVerifier providerInternal = getProvider(jwsHeaders);
  336.        
  337.         boolean result = consumer.verifySignatureWith(providerInternal);
  338.         this.decodedPayload = consumer.getDecodedJwsPayload();
  339.         this.decodedPayloadAsByte = consumer.getDecodedJwsPayloadBytes();
  340.         return result;
  341.     }

  342.     private boolean verifyDetachedCompact(String jsonDetachedSignature, String jsonDetachedPayload) throws UtilsException {
  343.         return verifyCompactEngine(jsonDetachedSignature, jsonDetachedPayload);
  344.     }
  345.     private boolean verifyCompact(String jsonSignature) throws UtilsException {
  346.         return verifyCompactEngine(jsonSignature, null);
  347.     }
  348.     private boolean verifyCompactEngine(String jsonSignature, String jsonDetachedPayload) throws UtilsException {
  349.        
  350.         JwsCompactConsumer consumer = null;
  351.         if(jsonDetachedPayload==null) {
  352.             consumer = new JwsCompactConsumer(jsonSignature);
  353.         }
  354.         else {
  355.             consumer = new JwsCompactConsumer(jsonSignature, Base64UrlUtility.encode(jsonDetachedPayload));
  356.         }
  357.        
  358.         this.jwsDecodedHeaders = consumer.getJwsHeaders();
  359.         try {
  360.             this.decodedHeader = consumer.getDecodedJsonHeaders();
  361.         }catch(Exception e) {
  362.             // ignore
  363.         }
  364.        
  365.         JwsSignatureVerifier providerInternal = getProvider(this.jwsDecodedHeaders);
  366.                
  367.         boolean result = consumer.verifySignatureWith(providerInternal);
  368.         if(jsonDetachedPayload!=null) {
  369.             this.decodedPayload = jsonDetachedPayload;
  370.             this.decodedPayloadAsByte = jsonDetachedPayload.getBytes();
  371.         }
  372.         else {
  373.             this.decodedPayload = consumer.getDecodedJwsPayload();
  374.             this.decodedPayloadAsByte = consumer.getDecodedJwsPayloadBytes();
  375.         }
  376.         return result;
  377.     }
  378.    
  379.     public String getDecodedPayload() {
  380.         return this.decodedPayload;
  381.     }

  382.     public byte[] getDecodedPayloadAsByte() {
  383.         return this.decodedPayloadAsByte;
  384.     }
  385.    
  386.     public JwsHeaders getJwsDecodedHeaders() {
  387.         return this.jwsDecodedHeaders;
  388.     }
  389.    
  390.     public String getDecodedHeader() {
  391.         return this.decodedHeader;
  392.     }
  393.    
  394.     private X509Certificate x509Certificate;
  395.     private PublicKey publicKey;
  396.     private String kid;
  397.     public X509Certificate getX509Certificate() {
  398.         return this.x509Certificate;
  399.     }
  400.     public PublicKey getRsaPublicKey() {
  401.         return this.publicKey;
  402.     }
  403.     public String getKid() {
  404.         return this.kid;
  405.     }

  406.     private String getProcessErrorMsg(String mode, Exception e) {
  407.         return "Process '"+mode+"' error: "+e.getMessage();
  408.     }
  409.     private JwsSignatureVerifier getProvider(JwsHeaders jwsHeaders) throws UtilsException {
  410.        
  411.         JwsSignatureVerifier providerReturn = this.provider;
  412.         if(jwsHeaders==null) {
  413.             return providerReturn;
  414.         }
  415.                
  416.         if(this.dynamicProvider) {
  417.             /** String alias = JsonUtils.readAlias(jsonSignature); */
  418.             String alias = jwsHeaders.getKeyId();
  419.             Properties pNew = new Properties();
  420.             pNew.putAll(this.properties);
  421.             /** System.out.println("ALIAS ["+alias+"]"); */
  422.             pNew.put(RSSecurityConstants.RSSEC_KEY_STORE_ALIAS, alias);
  423.             providerReturn = loadProviderFromProperties(pNew, jwsHeaders.getSignatureAlgorithm());
  424.         }
  425.        
  426.         if(providerReturn==null) {
  427.             org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm algo = jwsHeaders.getSignatureAlgorithm();
  428.             if(algo==null) {
  429.                 throw new UtilsException("SignatureAlgorithm not found");
  430.             }
  431.            
  432.             if(jwsHeaders.getX509Chain()!=null && !jwsHeaders.getX509Chain().isEmpty() && this.options.isPermitUseHeaderX5C()) {
  433.                 try {
  434.                     // https://tools.ietf.org/html/rfc7515#section-4.1.6: The certificate containing the public key corresponding to the key used to digitally sign the JWS MUST be the first certificate.
  435.                     byte [] cer = Base64Utilities.decode(jwsHeaders.getX509Chain().get(0));
  436.                     CertificateInfo certificatoInfo = ArchiveLoader.load(cer).getCertificate();
  437.                     if(this.trustStoreCertificatiX509!=null) {
  438.                         JsonUtils.validate(certificatoInfo,
  439.                                 this.trustStoreCertificatiX509, this.crlX509, this.ocspValidatorX509, JwtHeaders.JWT_HDR_X5C,
  440.                                 true,
  441.                                 this.validityCheck);
  442.                     }
  443.                     this.x509Certificate = certificatoInfo.getCertificate();
  444.                     providerReturn = JwsUtils.getPublicKeySignatureVerifier(this.x509Certificate, algo);
  445.                 }catch(Exception e) {
  446.                     throw new UtilsException(getProcessErrorMsg(JwtHeaders.JWT_HDR_X5C,e),e);
  447.                 }
  448.             }
  449.             else if(jwsHeaders.getJsonWebKey()!=null && this.options.isPermitUseHeaderJWK()) {
  450.                 try {
  451.                     this.publicKey = JwkUtils.toRSAPublicKey(jwsHeaders.getJsonWebKey());
  452.                     providerReturn = JwsUtils.getPublicKeySignatureVerifier(this.publicKey, algo);
  453.                 }catch(Exception e) {
  454.                     throw new UtilsException(getProcessErrorMsg(JwtHeaders.JWT_HDR_JWK,e),e);
  455.                 }
  456.             }
  457.             else if(
  458.                     (jwsHeaders.getX509Url()!=null && this.options.isPermitUseHeaderX5U())
  459.                     ||
  460.                     (jwsHeaders.getJsonWebKeysUrl()!=null && this.options.isPermitUseHeaderJKU())
  461.                     ) {
  462.                
  463.                 boolean x509 = true;
  464.                 String path = jwsHeaders.getX509Url();
  465.                 String hdr = JwtHeaders.JWT_HDR_X5U;
  466.                 if(path==null) {
  467.                     path=jwsHeaders.getJsonWebKeysUrl();
  468.                     x509 = false;
  469.                     hdr = JwtHeaders.JWT_HDR_JKU;
  470.                 }
  471.                 try {
  472.                     String prefixPath = "Resource '"+path+"'";
  473.                     byte [] cer = null;
  474.                     if(this.properties!=null) {
  475.                         this.properties.put(RSSecurityConstants.RSSEC_KEY_STORE_FILE, path);
  476.                         cer = JsonUtils.readKeystoreFromURI(this.properties);
  477.                     }
  478.                     else {
  479.                         HttpResponse httpResponse = getHttpResponse(path, prefixPath);
  480.                         if(httpResponse==null || httpResponse.getContent()==null) {
  481.                             throw new UtilsException(prefixPath+" unavailable");
  482.                         }
  483.                         if(httpResponse.getResultHTTPOperation()!=200) {
  484.                             throw new UtilsException("Retrieve '"+path+"' failed (returnCode:"+httpResponse.getResultHTTPOperation()+")");
  485.                         }
  486.                         cer = httpResponse.getContent();
  487.                     }
  488.                     if(cer==null) {
  489.                         throw new UtilsException(prefixPath+" unavailable");
  490.                     }
  491.                     if(x509) {
  492.                         CertificateInfo certificatoInfo = ArchiveLoader.load(cer).getCertificate();
  493.                         if(this.trustStoreCertificatiX509!=null) {
  494.                             JsonUtils.validate(certificatoInfo,
  495.                                     this.trustStoreCertificatiX509, this.crlX509, this.ocspValidatorX509, hdr,
  496.                                     true,
  497.                                     this.validityCheck);
  498.                         }
  499.                         this.x509Certificate = certificatoInfo.getCertificate();
  500.                         providerReturn = JwsUtils.getPublicKeySignatureVerifier(this.x509Certificate, algo);
  501.                     }
  502.                     else {
  503.                         JWKSet set = new JWKSet(new String(cer));
  504.                         JsonWebKeys jsonWebKeysInternal = set.getJsonWebKeys();
  505.                         JsonWebKey jsonWebKey = null;
  506.                         if(jsonWebKeysInternal.size()==1) {
  507.                             jsonWebKey = jsonWebKeysInternal.getKeys().get(0);
  508.                         }
  509.                         else {
  510.                             if(jwsHeaders.getKeyId()==null) {
  511.                                 throw new UtilsException("Kid non definito e JwkSet contiene più di un certificato");
  512.                             }
  513.                             jsonWebKey = jsonWebKeysInternal.getKey(jwsHeaders.getKeyId());
  514.                         }
  515.                         if(jsonWebKey==null) {
  516.                             throw new UtilsException("JsonWebKey non trovata");
  517.                         }
  518.                         this.publicKey = JwkUtils.toRSAPublicKey(jsonWebKey);
  519.                         providerReturn = JwsUtils.getPublicKeySignatureVerifier(this.publicKey, algo);
  520.                     }
  521.                 }catch(Exception e) {
  522.                     throw new UtilsException(getProcessErrorMsg(hdr,e),e);
  523.                 }
  524.             }
  525.             else if(jwsHeaders.getKeyId()!=null && this.options.isPermitUseHeaderKID()) {
  526.                 try {
  527.                     this.kid = jwsHeaders.getKeyId();
  528.                     if(this.jsonWebKeys!=null) {
  529.                         JsonWebKey jsonWebKey = getJsonWebKeyByKidIgnoreException();
  530.                         if(jsonWebKey!=null) {
  531.                             this.publicKey = JwkUtils.toRSAPublicKey(jsonWebKey);
  532.                             providerReturn = JwsUtils.getPublicKeySignatureVerifier(this.publicKey, algo);
  533.                         }
  534.                     }
  535.                     if(providerReturn==null &&
  536.                         this.trustStoreCertificatiX509!=null &&
  537.                         this.trustStoreCertificatiX509.existsAlias(this.kid)) {
  538.                         Certificate cer = this.trustStoreCertificatiX509.getCertificate(this.kid);
  539.                         if(cer instanceof X509Certificate) {
  540.                             this.x509Certificate = (X509Certificate) cer;
  541.                            
  542.                             // La validazione serve per verificare la data e il crl
  543.                             JsonUtils.validate(new CertificateInfo(this.x509Certificate, this.kid),
  544.                                     this.trustStoreCertificatiX509, this.crlX509, this.ocspValidatorX509, JwtHeaders.JWT_HDR_KID,
  545.                                     false,
  546.                                     this.validityCheck);
  547.                            
  548.                             providerReturn = JwsUtils.getPublicKeySignatureVerifier(this.x509Certificate, algo);
  549.                         }
  550.                     }
  551.                     if(providerReturn==null &&
  552.                             this.remoteStoreProvider!=null && this.remoteStoreConfig!=null && this.remoteStoreKeyType!=null) {
  553.                         providerReturn = getProviderByRemoteStore(algo);
  554.                     }
  555.                     if(providerReturn==null) {
  556.                         throw new UtilsException("Certificato, corrispondente al kid '"+this.kid+"', non trovato nel TrustStore dei certificati");
  557.                     }
  558.                 }catch(Exception e) {
  559.                     throw new UtilsException(getProcessErrorMsg(JwtHeaders.JWT_HDR_KID,e),e);
  560.                 }
  561.             }
  562.             else if(
  563.                     (jwsHeaders.getX509ThumbprintSHA256()!=null && this.options.isPermitUseHeaderX5T_256())
  564.                     ||
  565.                     (jwsHeaders.getX509Thumbprint()!=null && this.options.isPermitUseHeaderX5T())
  566.                     ) {
  567.                 String hdr = JwtHeaders.JWT_HDR_X5T;
  568.                 if (jwsHeaders.getX509ThumbprintSHA256()!=null) {
  569.                     hdr = JwtHeaders.JWT_HDR_X5t_S256;
  570.                 }
  571.                 try {
  572.                     if(this.trustStoreCertificatiX509==null) {
  573.                         throw new UtilsException("TrustStore dei certificati non fornito");
  574.                     }
  575.                     Certificate cer = null;
  576.                     if(jwsHeaders.getX509ThumbprintSHA256()!=null) {
  577.                         cer = this.trustStoreCertificatiX509.getCertificateByDigestSHA256UrlEncoded(jwsHeaders.getX509ThumbprintSHA256());
  578.                     }
  579.                     else{
  580.                         cer = this.trustStoreCertificatiX509.getCertificateByDigestSHA1UrlEncoded(jwsHeaders.getX509Thumbprint());
  581.                     }
  582.                     if(cer==null) {
  583.                         throw new UtilsException("Certificato, corrispondente al digest indicato, non trovato nel TrustStore dei certificati");
  584.                     }  
  585.                     if(cer instanceof X509Certificate) {
  586.                         this.x509Certificate = (X509Certificate) cer;
  587.                        
  588.                         // La validazione serve per verificare la data e il crl
  589.                         JsonUtils.validate(new CertificateInfo(this.x509Certificate, hdr),
  590.                                 this.trustStoreCertificatiX509, this.crlX509, this.ocspValidatorX509, hdr,
  591.                                 false,
  592.                                 this.validityCheck);
  593.                        
  594.                         providerReturn = JwsUtils.getPublicKeySignatureVerifier(this.x509Certificate, algo);
  595.                     }
  596.                     else {
  597.                         throw new UtilsException("Certificato indicato non è nel formato X.509");
  598.                     }
  599.                 }catch(Exception e) {
  600.                     throw new UtilsException(getProcessErrorMsg(hdr,e),e);
  601.                 }
  602.             }
  603.             else {
  604.                 List<String> hdrNotPermitted = this.options.headersNotPermitted(jwsHeaders);
  605.                 String notPermitted = "";
  606.                 if(hdrNotPermitted!=null && !hdrNotPermitted.isEmpty()) {
  607.                     notPermitted = "; header trovati ma non abilitati all'utilizzo: "+hdrNotPermitted;
  608.                 }
  609.                 throw new UtilsException("Non è stato trovato alcun header che consentisse di recuperare il certificato per effettuare la validazione"+notPermitted);
  610.             }
  611.         }
  612.         else {
  613.             if(this.x509Certificate==null && providerReturn instanceof org.apache.cxf.rs.security.jose.jws.PublicKeyJwsSignatureVerifier) {
  614.                 org.apache.cxf.rs.security.jose.jws.PublicKeyJwsSignatureVerifier certVer = (org.apache.cxf.rs.security.jose.jws.PublicKeyJwsSignatureVerifier) providerReturn;
  615.                 this.x509Certificate = certVer.getX509Certificate();
  616.                
  617.                 KeyStore trustStore = this.trustStoreCertificatiX509;
  618.                 if(trustStore==null &&
  619.                     this.propsConfig!=null) {
  620.                     trustStore = JsonUtils.getKeyStore(this.jksPasswordRequired, this.pkcs12PasswordRequired, this.propsConfig);
  621.                 }
  622.                
  623.                 if(trustStore!=null) {
  624.                     try {
  625.                         CertificateInfo certificatoInfo = new CertificateInfo(this.x509Certificate, "x509");
  626.                         JsonUtils.validate(certificatoInfo,
  627.                                 trustStore, this.crlX509, this.ocspValidatorX509, null, true,
  628.                                 this.validityCheck);
  629.                     }catch(Exception e) {
  630.                         throw new UtilsException(e.getMessage(),e);
  631.                     }
  632.                 }
  633.             }
  634.         }
  635.        
  636.         return providerReturn;
  637.     }
  638.    
  639.     private JsonWebKey getJsonWebKeyByKidIgnoreException(){
  640.         try {
  641.             return this.jsonWebKeys.getKey(this.kid);
  642.         }catch(Exception e) {
  643.             // key not found
  644.         }
  645.         return null;
  646.     }
  647.    
  648.     private HttpResponse getHttpResponse(String path, String prefixPath) throws UtilsException{
  649.         HttpResponse httpResponse = null;
  650.         try {
  651.             if(this.trustStoreHttps!=null) {
  652.                 httpResponse = HttpUtilities.getHTTPSResponse(path, this.trustStoreHttps.getKeystore(), this.crlHttps, this.ocspValidatorHttps);
  653.             }
  654.             else {
  655.                 httpResponse = HttpUtilities.getHTTPResponse(path);
  656.             }
  657.         }catch(Exception e) {
  658.             throw new UtilsException(prefixPath+" unavailable: "+e.getMessage(),e);
  659.         }
  660.         return httpResponse;
  661.     }
  662.    
  663.     private JwsSignatureVerifier getProviderByRemoteStore(org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm algo) throws UtilsException {
  664.         switch (this.remoteStoreKeyType) {
  665.         case JWK:
  666.             JWK jwk = this.remoteStoreProvider.readJWK(this.kid, this.remoteStoreConfig);
  667.             if(jwk==null) {
  668.                 throw this.newUtilsExceptionErrorKidUnavailable(true);
  669.             }
  670.             JsonWebKey jsonWebKey = jwk.getJsonWebKey();
  671.             if(jsonWebKey!=null) {
  672.                 this.publicKey = JwkUtils.toRSAPublicKey(jsonWebKey);
  673.                 return JwsUtils.getPublicKeySignatureVerifier(this.publicKey, algo);
  674.             }
  675.             else {
  676.                 throw this.newUtilsExceptionErrorKidUnavailable(true);
  677.             }
  678.         case PUBLIC_KEY:
  679.             this.publicKey = this.remoteStoreProvider.readPublicKey(this.kid, this.remoteStoreConfig);
  680.             if(this.publicKey==null) {
  681.                 throw this.newUtilsExceptionErrorKidUnavailable(true);
  682.             }
  683.             return JwsUtils.getPublicKeySignatureVerifier(this.publicKey, algo);
  684.         case X509:
  685.             org.openspcoop2.utils.certificate.Certificate certificate = this.remoteStoreProvider.readX509(this.kid, this.remoteStoreConfig);
  686.             if(certificate==null) {
  687.                 throw this.newUtilsExceptionErrorKidUnavailable(false);
  688.             }
  689.             this.x509Certificate = certificate.getCertificate().getCertificate();
  690.             return JwsUtils.getPublicKeySignatureVerifier(this.x509Certificate, algo);
  691.         default:
  692.             throw new UtilsException("RemoteStoreKeyType '"+this.remoteStoreKeyType+"' unknown");
  693.         }
  694.     }
  695.     private UtilsException newUtilsExceptionErrorKidUnavailable(boolean publicKey) {
  696.         String prefix = publicKey? "Public Key" : "Certificate";
  697.         return new UtilsException(prefix+" with kid '"+this.kid+"' unavailable");
  698.     }
  699. }