KeyPairStore.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.security.keystore;

  21. import java.io.Serializable;
  22. import java.security.PrivateKey;
  23. import java.security.PublicKey;
  24. import java.util.UUID;

  25. import org.openspcoop2.security.SecurityException;
  26. import org.openspcoop2.utils.certificate.JWKPrivateKeyConverter;
  27. import org.openspcoop2.utils.certificate.JWKSet;
  28. import org.openspcoop2.utils.certificate.KeyUtils;
  29. import org.openspcoop2.utils.certificate.byok.BYOKRequestParams;

  30. /**
  31.  * KeyPairStore
  32.  *
  33.  * @author Andrea Poli (apoli@link.it)
  34.  * @author $Author$
  35.  * @version $Rev$, $Date$
  36.  */
  37. public class KeyPairStore implements Serializable {

  38.     /**
  39.      *
  40.      */
  41.     private static final long serialVersionUID = 1L;
  42.    
  43.     private String privateKeyPath;
  44.     private String publicKeyPath;
  45.    
  46.     private byte[] privateKeyContent;
  47.     private byte[] publicKeyContent;
  48.     private transient PrivateKey privateKey;
  49.     private transient PublicKey publicKey;
  50.    
  51.     private String privateKeyPassword;
  52.     private String algorithm;
  53.    
  54.     private String jwkSetContent;
  55.     private String jwkSetKid;
  56.     private transient JWKSet jwkSet;

  57.     @Override
  58.     public String toString() {
  59.         StringBuilder bf = new StringBuilder();
  60.         bf.append("KeyPairStore (private:").append(this.privateKeyPath).append(" public:").append(this.publicKeyPath).append(")");
  61.         return bf.toString();
  62.     }
  63.    
  64.     public KeyPairStore(String privateKeyPath, String publicKeyPath, String privateKeyPassword, String algorithm) throws SecurityException{
  65.         this(privateKeyPath, publicKeyPath, privateKeyPassword, algorithm, null);
  66.     }
  67.     public KeyPairStore(String privateKeyPath, String publicKeyPath, String privateKeyPassword, String algorithm, BYOKRequestParams requestParams) throws SecurityException{

  68.         this.privateKeyPath = privateKeyPath;
  69.         this.publicKeyPath = publicKeyPath;
  70.                
  71.         this.privateKeyPassword = privateKeyPassword;
  72.         this.algorithm = algorithm==null ? KeyUtils.ALGO_RSA : algorithm;
  73.        
  74.         this.privateKeyContent = StoreUtils.readContent("PrivateKey", this.privateKeyPath);
  75.         this.privateKeyContent = StoreUtils.unwrapBYOK(this.privateKeyContent, requestParams);
  76.        
  77.         this.publicKeyContent = StoreUtils.readContent("PublicKey", this.publicKeyPath);
  78.        
  79.     }
  80.    
  81.     public KeyPairStore(String privateKeyPath, byte[] publicKey, String privateKeyPassword, String algorithm) throws SecurityException{
  82.         this(privateKeyPath, publicKey, privateKeyPassword, algorithm, null);
  83.     }
  84.     public KeyPairStore(String privateKeyPath, byte[] publicKey, String privateKeyPassword, String algorithm, BYOKRequestParams requestParams) throws SecurityException{

  85.         this.privateKeyPath = privateKeyPath;
  86.        
  87.         if(publicKey==null){
  88.             throw new SecurityException("Store publicKey non indicato");
  89.         }
  90.         this.publicKeyContent = publicKey;
  91.                
  92.         this.privateKeyPassword = privateKeyPassword;
  93.         this.algorithm = algorithm==null ? KeyUtils.ALGO_RSA : algorithm;
  94.        
  95.         this.privateKeyContent = StoreUtils.readContent("PrivateKey", this.privateKeyPath);
  96.         this.privateKeyContent = StoreUtils.unwrapBYOK(this.privateKeyContent, requestParams);
  97.                
  98.     }
  99.    
  100.     public KeyPairStore(byte[] privateKey, byte[] publicKey, String privateKeyPassword, String algorithm) throws SecurityException{
  101.         this(privateKey, publicKey, privateKeyPassword, algorithm, null);
  102.     }
  103.     public KeyPairStore(byte[] privateKey, byte[] publicKey, String privateKeyPassword, String algorithm, BYOKRequestParams requestParams) throws SecurityException{

  104.         try{
  105.             if(privateKey==null){
  106.                 throw new SecurityException("Store privateKey non indicato");
  107.             }
  108.             this.privateKeyContent = privateKey;
  109.             this.privateKeyContent = StoreUtils.unwrapBYOK(this.privateKeyContent, requestParams);
  110.            
  111.             if(publicKey==null){
  112.                 throw new SecurityException("Store publicKey non indicato");
  113.             }
  114.             this.publicKeyContent = publicKey;
  115.            
  116.             this.privateKeyPassword = privateKeyPassword;
  117.             this.algorithm = algorithm==null ? KeyUtils.ALGO_RSA : algorithm;
  118.            
  119.         }catch(Exception e){
  120.             throw new SecurityException(e.getMessage(),e);
  121.         }
  122.        
  123.     }
  124.    
  125.     public KeyPairStore(byte[] privateKey, String publicKeyPath, String privateKeyPassword, String algorithm) throws SecurityException{
  126.         this(privateKey, publicKeyPath, privateKeyPassword, algorithm, null);
  127.     }
  128.     public KeyPairStore(byte[] privateKey, String publicKeyPath, String privateKeyPassword, String algorithm, BYOKRequestParams requestParams) throws SecurityException{

  129.         try{
  130.             if(privateKey==null){
  131.                 throw new SecurityException("Store privateKey non indicato");
  132.             }
  133.             this.privateKeyContent = privateKey;
  134.             this.privateKeyContent = StoreUtils.unwrapBYOK(this.privateKeyContent, requestParams);
  135.            
  136.             this.publicKeyPath = publicKeyPath;
  137.            
  138.             this.privateKeyPassword = privateKeyPassword;
  139.             this.algorithm = algorithm==null ? KeyUtils.ALGO_RSA : algorithm;
  140.    
  141.             this.publicKeyContent = StoreUtils.readContent("PublicKey", this.publicKeyPath);
  142.            
  143.         }catch(Exception e){
  144.             throw new SecurityException(e.getMessage(),e);
  145.         }
  146.        
  147.     }

  148.    
  149.     public PrivateKey getPrivateKey() throws SecurityException {
  150.         if(this.privateKey==null) {
  151.             initializePrivateKey();
  152.         }
  153.         return this.privateKey;
  154.     }
  155.     private synchronized void initializePrivateKey() throws SecurityException {
  156.         if(this.privateKey==null) {
  157.             try {
  158.                 if(this.privateKeyPassword==null) {
  159.                     this.privateKey = KeyUtils.getInstance(this.algorithm).getPrivateKey(this.privateKeyContent);
  160.                 }
  161.                 else {
  162.                     this.privateKey = KeyUtils.getInstance(this.algorithm).getPrivateKey(this.privateKeyContent, this.privateKeyPassword);
  163.                 }
  164.             }catch(Exception e){
  165.                 if(this.privateKeyPassword==null && e.getMessage().contains("org.bouncycastle.openssl.PEMEncryptedKeyPair cannot be cast to class org.bouncycastle.openssl.PEMKeyPair")) {
  166.                     throw new SecurityException("Load private key failed: encrypted key require key password",e);
  167.                 }
  168.                 else {
  169.                     throw new SecurityException("Load private key failed: "+e.getMessage(),e);
  170.                 }
  171.             }
  172.         }
  173.     }
  174.    
  175.    
  176.     public PublicKey getPublicKey() throws SecurityException {
  177.         if(this.publicKey==null) {
  178.             initializePublicKey();
  179.         }
  180.         return this.publicKey;
  181.     }
  182.     private synchronized void initializePublicKey() throws SecurityException {
  183.         if(this.publicKey==null) {
  184.             try {
  185.                 this.publicKey = KeyUtils.getInstance(this.algorithm).getPublicKey(this.publicKeyContent);
  186.             }catch(Exception e){
  187.                 throw new SecurityException("Load public key failed: "+e.getMessage(),e);
  188.             }
  189.         }
  190.     }
  191.    
  192.    
  193.     public JWKSet getJwkSet() throws SecurityException {
  194.         if(this.jwkSet==null) {
  195.             initializeJwkSet();
  196.         }
  197.         return this.jwkSet;
  198.     }
  199.     private synchronized void initializeJwkSet() throws SecurityException {
  200.         if(this.jwkSet==null) {
  201.             if(this.jwkSetContent==null) {
  202.                 this.jwkSetKid = UUID.randomUUID().toString();
  203.                 try {
  204.                     this.jwkSetContent = JWKPrivateKeyConverter.convert(this.getPublicKey(), this.getPrivateKey(), this.jwkSetKid, true, false);
  205.                 }catch(Exception e){
  206.                     throw new SecurityException(e.getMessage(),e);
  207.                 }
  208.             }
  209.                        
  210.             this.jwkSet = new JWKSet(this.jwkSetContent);
  211.         }
  212.     }
  213.    
  214.     public String getJwkSetKid() {
  215.         return this.jwkSetKid;
  216.     }
  217. }