Skip to content

Commit

Permalink
[DROOLS-7001] Update KeyStoreHelper signature (apache#4448) (apache#4572
Browse files Browse the repository at this point in the history
)
  • Loading branch information
tkobayas authored Jul 29, 2022
1 parent 4b41387 commit b598eb8
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,7 @@ public class KeyStoreConstants {
public static final String KEY_CERTIFICATE_TYPE = "JKS";

public static final String KEY_PASSWORD_TYPE = "JCEKS";

// true if you allow verifying with old sign algorithm "MD5withRSA"
public static final String PROP_VERIFY_OLD_SIGN = "drools.serialization.verify.old.sign";
}
37 changes: 34 additions & 3 deletions drools-core/src/main/java/org/drools/core/util/KeyStoreHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@
*/
public class KeyStoreHelper {

private static final String SHA512WITH_RSA = "SHA512withRSA";
private static final String MD5WITH_RSA = "MD5withRSA";

private boolean signed;
private boolean allowVerifyOldSignAlgo;

private URL pvtKeyStoreURL;
private char[] pvtKeyStorePwd;
Expand All @@ -85,6 +89,7 @@ public class KeyStoreHelper {
try {
this.signed = Boolean.valueOf(System.getProperty(KeyStoreConstants.PROP_SIGN,
RuleBaseConfiguration.DEFAULT_SIGN_ON_SERIALIZATION)).booleanValue();
this.allowVerifyOldSignAlgo = Boolean.parseBoolean(System.getProperty(KeyStoreConstants.PROP_VERIFY_OLD_SIGN, "false"));

loadPrivateKeyStoreProperties();
loadPublicKeyStoreProperties();
Expand Down Expand Up @@ -178,12 +183,25 @@ public byte[] signDataWithPrivateKey(byte[] data) throws UnrecoverableKeyExcepti
}
PrivateKey pvtkey = (PrivateKey) pvtKeyStore.getKey( pvtKeyAlias,
pvtKeyPassword );
Signature sig = Signature.getInstance( "MD5withRSA" );
Signature sig = Signature.getInstance( SHA512WITH_RSA );
sig.initSign( pvtkey );
sig.update( data );
return sig.sign();
}

// test purpose
byte[] signDataWithPrivateKeyWithAlgorithm(byte[] data, String algorithm) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
if (pvtKeyStore == null) {
throw new RuntimeException("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(algorithm);
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
Expand Down Expand Up @@ -212,10 +230,23 @@ public boolean checkDataWithPublicKey(final String publicKeyAlias,
if( cert == null ) {
throw new RuntimeException( "Public certificate for key '"+publicKeyAlias+"' not found in the configured key store. Impossible to deserialize the object." );
}
Signature sig = Signature.getInstance( "MD5withRSA" );
Signature sig = Signature.getInstance( SHA512WITH_RSA );
sig.initVerify( cert.getPublicKey() );
sig.update( data );
return sig.verify( signature );
try {
return sig.verify( signature );
} catch (SignatureException e) {
if (allowVerifyOldSignAlgo) {
// Fallback for old sign algorithm
sig = Signature.getInstance(MD5WITH_RSA);
sig.initVerify(cert.getPublicKey());
sig.update(data);
return sig.verify(signature);
} else {
throw new RuntimeException("Failed to verify signature. If you call this method for data signed by old Drools version," +
" set system property \"" + KeyStoreConstants.PROP_VERIFY_OLD_SIGN + "\" to true" , e);
}
}
}

public String getPasswordKey(String pwdKeyAlias, char[] pwdKeyPassword) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,49 @@ private SecretKey storeKeyIntoKeyStoreFile(final String keyPhrase)
}
return mySecretKey;
}

@Test
public void testSignDataWithPrivateKeyWithFallback() throws UnsupportedEncodingException, UnrecoverableKeyException, InvalidKeyException, KeyStoreException, NoSuchAlgorithmException, SignatureException {
// The server signs the data with the private key

try {
// Set properties to simulate the server
final URL serverKeyStoreURL = getClass().getResource(KEYSTORE_SERVER_RESOURCE_NAME);
System.setProperty(KeyStoreConstants.PROP_SIGN, Boolean.TRUE.toString());
System.setProperty(KeyStoreConstants.PROP_VERIFY_OLD_SIGN, Boolean.TRUE.toString()); // allow fallback
System.setProperty(KeyStoreConstants.PROP_PVT_KS_URL, serverKeyStoreURL.toExternalForm());
System.setProperty(KeyStoreConstants.PROP_PVT_KS_PWD, KEYSTORE_SERVER_PASSWORD);
System.setProperty(KeyStoreConstants.PROP_PVT_ALIAS, KEY_ALIAS);
System.setProperty(KeyStoreConstants.PROP_PVT_PWD, KEY_PASSWORD);
final KeyStoreHelper serverHelper = new KeyStoreHelper();

// get some data to sign
final byte[] data = "Hello World".getBytes("UTF8");

// sign the data with MD5withRSA
final byte[] signature = serverHelper.signDataWithPrivateKeyWithAlgorithm(data, "MD5withRSA");

// now, initialise the client helper

// Set properties to simulate the client
final URL clientKeyStoreURL = getClass().getResource(KEYSTORE_CLIENT_RESOURCE_NAME);
System.setProperty(KeyStoreConstants.PROP_SIGN, Boolean.TRUE.toString());
System.setProperty(KeyStoreConstants.PROP_PUB_KS_URL, clientKeyStoreURL.toExternalForm());
System.setProperty(KeyStoreConstants.PROP_PUB_KS_PWD, KEYSTORE_CLIENT_PASSWORD);
// client needs no password to access the certificate and public key
final KeyStoreHelper clientHelper = new KeyStoreHelper();

// check the signature against the data
assertTrue(clientHelper.checkDataWithPublicKey(KEY_ALIAS,
data,
signature));

// check some fake data
assertFalse(clientHelper.checkDataWithPublicKey(KEY_ALIAS,
"fake".getBytes("UTF8"),
signature));
} finally {
System.clearProperty(KeyStoreConstants.PROP_VERIFY_OLD_SIGN);
}
}
}

0 comments on commit b598eb8

Please sign in to comment.