JsonSignature.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.security;
- import java.security.PrivateKey;
- import java.util.Iterator;
- import java.util.Properties;
- import javax.crypto.SecretKey;
- import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
- import org.apache.cxf.rs.security.jose.jwk.JsonWebKeys;
- import org.apache.cxf.rs.security.jose.jwk.JwkUtils;
- import org.apache.cxf.rs.security.jose.jws.JwsCompactProducer;
- import org.apache.cxf.rs.security.jose.jws.JwsException;
- import org.apache.cxf.rs.security.jose.jws.JwsHeaders;
- import org.apache.cxf.rs.security.jose.jws.JwsJsonProducer;
- import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider;
- import org.apache.cxf.rs.security.jose.jws.JwsUtils;
- import org.openspcoop2.utils.UtilsException;
- import org.openspcoop2.utils.certificate.KeyStore;
- import org.openspcoop2.utils.certificate.KeystoreType;
- /**
- * JsonSignature
- *
- * @author Poli Andrea (apoli@link.it)
- * @author $Author$
- * @version $Rev$, $Date$
- */
- public class JsonSignature {
- private JwsSignatureProvider provider;
- private JWSOptions options;
- private JwsHeaders headers;
- private JwtHeaders jwtHeaders;
-
- public JsonSignature(Properties props, JWSOptions options) throws UtilsException{
- this(props, null, options);
- }
- public JsonSignature(Properties props, JwtHeaders jwtHeaders, JWSOptions options) throws UtilsException{
- try {
- this.headers = new JwsHeaders(props);
- this.provider = JsonUtils.getJwsSymmetricProvider(props);
- if(this.provider==null) {
- try {
- this.provider = JwsUtils.loadSignatureProvider(JsonUtils.newMessage(), props, this.headers);
- }catch(JwsException jwsExc) {
- if(jwsExc.getMessage()!=null && jwsExc.getMessage().contains("NO_PROVIDER")) {
- // caso in cui la chiave privata PKCS11 non e' stata mappata in un PrivateKeyJwsSignatureProvider
- // caso pkcs11 dove la chiave privata non e' ne ECPrivateKey ne RSAPrivateKey gestita dal metodo getPrivateKeySignatureProvider
- // ad es. può essere sun.security.pkcs11.P11Key$P11PrivateKey
- this.provider = JsonUtils.getJwsAsymmetricProvider(props);
- if(this.provider==null) {
- // rilancio eccezione precedente
- throw jwsExc;
- }
- }
- }
- }
- this.options=options;
- this.jwtHeaders = jwtHeaders;
- }catch(Exception t) {
- throw JsonUtils.convert(options.getSerialization(), JsonUtils.SIGNATURE,JsonUtils.SENDER,t);
- }
- }
- public JsonSignature(java.security.KeyStore keystore, boolean secretKey, String alias, String passwordPrivateKey, String signatureAlgorithm, JWSOptions options) throws UtilsException{
- this(new KeyStore(keystore), secretKey, alias, passwordPrivateKey, signatureAlgorithm,
- null, options);
- }
- public JsonSignature(KeyStore keystore, boolean secretKey, String alias, String passwordPrivateKey, String signatureAlgorithm, JWSOptions options) throws UtilsException{
- this(keystore, secretKey, alias, passwordPrivateKey, signatureAlgorithm,
- null, options);
- }
- public JsonSignature(java.security.KeyStore keystore, boolean secretKey, String alias, String passwordPrivateKey, String signatureAlgorithm,
- JwtHeaders jwtHeaders, JWSOptions options) throws UtilsException{
- this(new KeyStore(keystore),secretKey, alias, passwordPrivateKey, signatureAlgorithm, jwtHeaders, options);
- }
- public JsonSignature(KeyStore keystore, boolean secretKey, String alias, String passwordPrivateKey, String signatureAlgorithm,
- JwtHeaders jwtHeaders, JWSOptions options) throws UtilsException{
- try {
-
- org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm algo = org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm.getAlgorithm(signatureAlgorithm);
- if(secretKey) {
- String tipo = KeystoreType.JCEKS.getLabel();
- SecretKey secret = keystore.getSecretKey(alias, passwordPrivateKey);
- if(KeystoreType.PKCS11.getNome().equalsIgnoreCase(keystore.getKeystoreType())) {
- tipo = KeystoreType.PKCS11.getLabel();
- SecretKeyPkcs11 secretKeyPkcs11 = new SecretKeyPkcs11(keystore.getKeystoreProvider(), secret);
- this.provider = new HmacJwsSignatureProviderExtended(secretKeyPkcs11, algo);
- }
- else {
- this.provider = JwsUtils.getHmacSignatureProvider(secret.getEncoded(), algo);
- }
- if(this.provider==null) {
- throw new UtilsException("("+tipo+") JwsSignatureProvider init failed; check signature algorithm ("+signatureAlgorithm+")");
- }
- }
- else {
- PrivateKey pKey = keystore.getPrivateKey(alias, passwordPrivateKey);
- this.provider = JwsUtils.getPrivateKeySignatureProvider(pKey, algo);
- if(this.provider==null) {
- // caso in cui la chiave privata PKCS11 non e' stata mappata in un PrivateKeyJwsSignatureProvider
- // caso pkcs11 dove la chiave privata non e' ne ECPrivateKey ne RSAPrivateKey gestita dal metodo getPrivateKeySignatureProvider
- // ad es. può essere sun.security.pkcs11.P11Key$P11PrivateKey
- this.provider = JsonUtils.getJwsAsymmetricProvider(pKey, algo);
- if(this.provider==null) {
- throw new UtilsException("("+keystore.getKeystore().getType()+") JwsSignatureProvider init failed; check signature algorithm ("+signatureAlgorithm+")");
- }
- }
- }
- this.options=options;
- this.jwtHeaders = jwtHeaders;
- }catch(Exception t) {
- throw JsonUtils.convert(options.getSerialization(), JsonUtils.SIGNATURE,JsonUtils.SENDER,t);
- }
- }
-
- public JsonSignature(JsonWebKeys jsonWebKeys, boolean secretKey, String alias, String signatureAlgorithm, JWSOptions options) throws UtilsException{
- this(jsonWebKeys, secretKey, alias, signatureAlgorithm,
- null, options);
- }
- public JsonSignature(JsonWebKeys jsonWebKeys, boolean secretKey, String alias, String signatureAlgorithm,
- JwtHeaders jwtHeaders, JWSOptions options) throws UtilsException{
- this(JsonUtils.readKey(jsonWebKeys, alias),secretKey,signatureAlgorithm,jwtHeaders,options);
- }
-
- public JsonSignature(JsonWebKey jsonWebKey, boolean secretKey, String signatureAlgorithm, JWSOptions options) throws UtilsException{
- this(jsonWebKey, secretKey, signatureAlgorithm,
- null, options);
- }
- public JsonSignature(JsonWebKey jsonWebKey, boolean secretKey, String signatureAlgorithm,
- JwtHeaders jwtHeaders, JWSOptions options) throws UtilsException{
- try {
- org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm algo = org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm.getAlgorithm(signatureAlgorithm);
- if(secretKey) {
- this.provider = JwsUtils.getSignatureProvider(jsonWebKey, algo);
- if(this.provider==null) {
- throw new UtilsException("(JsonWebKey) JwsSignatureProvider init failed; check signature algorithm ("+signatureAlgorithm+")");
- }
- }else {
- this.provider = JwsUtils.getPrivateKeySignatureProvider(JwkUtils.toRSAPrivateKey(jsonWebKey), algo);
- }
- this.options=options;
- this.jwtHeaders = jwtHeaders;
- }catch(Exception t) {
- throw JsonUtils.convert(options.getSerialization(), JsonUtils.SIGNATURE,JsonUtils.SENDER,t);
- }
- }
- public JsonSignature(String secret, String signatureAlgorithm, JWSOptions options) throws UtilsException{
- this(secret, signatureAlgorithm, null, options);
- }
- public JsonSignature(String secret, String signatureAlgorithm, JwtHeaders jwtHeaders, JWSOptions options) throws UtilsException{
- try {
-
- org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm algo = org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm.getAlgorithm(signatureAlgorithm);
- this.provider = JwsUtils.getHmacSignatureProvider(secret.getBytes(), algo);
- if(this.provider==null) {
- throw new UtilsException("(Secret) JwsSignatureProvider init failed; check signature algorithm ("+signatureAlgorithm+")");
- }
- this.options=options;
- this.jwtHeaders = jwtHeaders;
- }catch(Exception t) {
- throw JsonUtils.convert(options.getSerialization(), JsonUtils.SIGNATURE,JsonUtils.SENDER,t);
- }
- }
- public String sign(String jsonString) throws UtilsException{
- try {
- switch(this.options.getSerialization()) {
- case JSON: return signJson(jsonString);
- case COMPACT: return signCompact(jsonString);
- default: throw new UtilsException("Unsupported serialization '"+this.options.getSerialization()+"'");
- }
- }
- catch(Exception t) {
- throw JsonUtils.convert(this.options.getSerialization(), JsonUtils.SIGNATURE,JsonUtils.SENDER,t);
- }
- }
- private String signCompact(String jsonString) throws Exception {
- JwsHeaders headersInternal = new JwsHeaders(this.provider.getAlgorithm());
- // utilizzabile solamente per JSON. Per COMPACT è sconsigliato poichè limitato nei caratteri, non utilizzabile quindi per un json https://tools.ietf.org/html/rfc7797#page-8
- // Infatti JwsCompactProducer di cxf non lo implementa proprio se si va a vedere il codice, il metodo 'getUnsignedEncodedJws' utilizzato per comporre il jwt non prevede il caso di lasciarlo in chiaro
- /** if(this.options.isPayloadEncoding()==false) {
- // headers.setPayloadEncodingStatus(this.options.isPayloadEncoding()); // RFC: https://tools.ietf.org/html/rfc7797
- // }*/
- JwsCompactProducer jwsProducer = new JwsCompactProducer(headersInternal, jsonString, this.options.isDetached());
- fillJwtHeaders(jwsProducer.getJwsHeaders(), this.provider.getAlgorithm());
- return jwsProducer.signWith(this.provider);
- }
- private String signJson(String jsonString) throws Exception {
- JwsJsonProducer jwsProducer = new JwsJsonProducer(jsonString, false, this.options.isDetached());
- JwsHeaders headersInternal = new JwsHeaders(this.provider.getAlgorithm());
- if(!this.options.isPayloadEncoding()) {
- headersInternal.setPayloadEncodingStatus(this.options.isPayloadEncoding()); // RFC: https://tools.ietf.org/html/rfc7797
- }
- fillJwtHeaders(headersInternal, this.provider.getAlgorithm());
- return jwsProducer.signWith(this.provider, headersInternal);
- }
-
- private void fillJwtHeaders(JwsHeaders headers,
- org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm signatureAlgo) throws Exception {
- if(this.headers!=null &&
- this.headers.asMap()!=null && !this.headers.asMap().isEmpty()) {
- Iterator<String> itKeys = this.headers.asMap().keySet().iterator();
- while (itKeys.hasNext()) {
- String key = itKeys.next();
- if(!headers.containsHeader(key)) {
- headers.setHeader(key, this.headers.getHeader(key));
- }
- }
- }
- if(this.jwtHeaders!=null) {
- this.jwtHeaders.fillJwsHeaders(headers, false, signatureAlgo.getJwaName());
- }
- }
- }