/** * */ package org.drools.core.util; import java.io.IOException; import java.net.URL; import java.security.InvalidKeyException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Signature; import java.security.SignatureException; import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.util.Properties; import org.drools.RuleBaseConfiguration; import org.drools.RuntimeDroolsException; /** * A helper class to deal with the key store and signing process during * Serialisation * * This class will read and use the following system properties: * * drools.serialization.sign = <false|true> * drools.serialization.private.keyStoreURL = <URL> * drools.serialization.private.keyStorePwd = <password> * drools.serialization.private.keyAlias = <key> * drools.serialization.private.keyPwd = <password> * drools.serialization.public.keyStoreURL = <URL> * drools.serialization.public.keyStorePwd = <password> * * @author etirelli * */ public class KeyStoreHelper { // true if packages should be signed during serialization public static final String PROP_SIGN = "drools.serialization.sign"; // the URL to the key store where the private key is stored public static final String PROP_PVT_KS_URL = "drools.serialization.private.keyStoreURL"; // the key store password public static final String PROP_PVT_KS_PWD = "drools.serialization.private.keyStorePwd"; // the private key identifier public static final String PROP_PVT_ALIAS = "drools.serialization.private.keyAlias"; // the private key password public static final String PROP_PVT_PWD = "drools.serialization.private.keyPwd"; // the URL to the key store where the public key is stored public static final String PROP_PUB_KS_URL = "drools.serialization.public.keyStoreURL"; // the key store password public static final String PROP_PUB_KS_PWD = "drools.serialization.public.keyStorePwd"; private boolean signed; private URL pvtKeyStoreURL; private char[] pvtKeyStorePwd; private String pvtKeyAlias; private char[] pvtKeyPassword; private URL pubKeyStoreURL; private char[] pubKeyStorePwd; private KeyStore pvtKeyStore; private KeyStore pubKeyStore; /** * Creates a KeyStoreHelper and initialises the KeyStore, by loading its entries. * * @throws RuntimeDroolsException in case any error happens when initialising and loading the keystore. */ public KeyStoreHelper() { try { Properties prop = System.getProperties(); this.signed = Boolean.valueOf( prop.getProperty( PROP_SIGN, RuleBaseConfiguration.DEFAULT_SIGN_ON_SERIALIZATION ) ).booleanValue(); String url = prop.getProperty( PROP_PVT_KS_URL, "" ); if ( url.length() > 0 ) { this.pvtKeyStoreURL = new URL( url ); } this.pvtKeyStorePwd = prop.getProperty( PROP_PVT_KS_PWD, "" ).toCharArray(); this.pvtKeyAlias = prop.getProperty( PROP_PVT_ALIAS, "" ); this.pvtKeyPassword = prop.getProperty( PROP_PVT_PWD, "" ).toCharArray(); url = prop.getProperty( PROP_PUB_KS_URL, "" ); if ( url.length() > 0 ) { this.pubKeyStoreURL = new URL( url ); } this.pubKeyStorePwd = prop.getProperty( PROP_PUB_KS_PWD, "" ).toCharArray(); initKeyStore(); } catch ( Exception e ) { throw new RuntimeDroolsException( "Error initialising KeyStore: " + e.getMessage(), e ); } } private void initKeyStore() throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException { if ( pvtKeyStoreURL != null ) { this.pvtKeyStore = KeyStore.getInstance( "JKS" ); this.pvtKeyStore.load( pvtKeyStoreURL.openStream(), pvtKeyStorePwd ); } if ( pubKeyStoreURL != null ) { this.pubKeyStore = KeyStore.getInstance( "JKS" ); this.pubKeyStore.load( pubKeyStoreURL.openStream(), pubKeyStorePwd ); } } /** * Generates the signature for the given byte[] using MD5 with RSA algorithm and the * private key with which this helper was initialised. * * @param data the byte[] of data to be signed * * @return the signature, encrypted with the private key * * @throws UnrecoverableKeyException * @throws KeyStoreException * @throws NoSuchAlgorithmException * @throws InvalidKeyException * @throws SignatureException */ public byte[] signDataWithPrivateKey(byte[] data) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, InvalidKeyException, SignatureException { if( pvtKeyStore == null ) { throw new RuntimeDroolsException( "Key store with private key not configured. Please configure it properly before using signed serialization." ); } PrivateKey pvtkey = (PrivateKey) pvtKeyStore.getKey( pvtKeyAlias, pvtKeyPassword ); Signature sig = Signature.getInstance( "MD5withRSA" ); sig.initSign( pvtkey ); sig.update( data ); return sig.sign(); } /** * Checks the given byte[] data against the signature, using the * public key with which this helper was initialised and the algorithm * MD5 with RSA. * * @param data the original data that was signed * @param signature the provided signature * * @return true in case the signature matches, false otherwise. * * @throws KeyStoreException * @throws NoSuchAlgorithmException * @throws InvalidKeyException * @throws SignatureException */ public boolean checkDataWithPublicKey(final String publicKeyAlias, final byte[] data, final byte[] signature) throws KeyStoreException, NoSuchAlgorithmException, InvalidKeyException, SignatureException { if( pubKeyStore == null ) { throw new RuntimeDroolsException( "Key store with public key not configured. Please configure it properly before using signed serialization." ); } Certificate cert = pubKeyStore.getCertificate( publicKeyAlias ); if( cert == null ) { throw new RuntimeDroolsException( "Public certificate for key '"+publicKeyAlias+"' not found in the configured key store. Impossible to deserialize the object." ); } Signature sig = Signature.getInstance( "MD5withRSA" ); sig.initVerify( cert.getPublicKey() ); sig.update( data ); return sig.verify( signature ); } public boolean isSigned() { return signed; } public URL getPvtKeyStoreURL() { return pvtKeyStoreURL; } public char[] getPvtKeyStorePwd() { return pvtKeyStorePwd; } public String getPvtKeyAlias() { return pvtKeyAlias; } public char[] getPvtKeyPassword() { return pvtKeyPassword; } public URL getPubKeyStoreURL() { return pubKeyStoreURL; } public char[] getPubKeyStorePwd() { return pubKeyStorePwd; } public KeyStore getPvtKeyStore() { return pvtKeyStore; } public KeyStore getPubKeyStore() { return pubKeyStore; } }