-
Bug
-
Resolution: Cannot Reproduce
-
P3
-
None
-
6u10
-
x86
-
windows_2003
FULL PRODUCT VERSION :
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) Client VM (build 11.0-b15, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Windows XP or 2003:
Microsoft Windows XP [Version 5.1.2600]
EXTRA RELEVANT SYSTEM CONFIGURATION :
PKCS11 config file:
name=BTHSM
library=C:\WINDOWS\system32\aetpkss1.dll
description=StarKey_64K_SmartCafe
slotListIndex=1
attributes(generate,CKO_PRIVATE_KEY,CKK_RSA) = {
CKA_TOKEN = true
CKA_SIGN = true
CKA_DECRYPT = true
CKA_SENSITIVE = true
CKA_PRIVATE = true
CKA_EXTRACTABLE = false
CKA_UNWRAP = true
}
attributes(*,CKO_PUBLIC_KEY,CKK_RSA) = {
CKA_ENCRYPT = true
CKA_VERIFY = true
CKA_VERIFY_RECOVER = true
CKA_WRAP = true
}
A DESCRIPTION OF THE PROBLEM :
I think there is a problem with SunPKCS11 KeyStore deleteEntry where it deletes more certs than it should do. I have a keystore with 2 entries:
IFMPROD_SIGN_008
IFMPROD_SIGN_007
all key entries are under the same CA hierarchy (issuing and root CA). I can use keytool to list with verbose and in each case see a nice 3 cert chain for each entry. I then use the deleteAlias to remove IFMPROD_SIGN_007 (either within a Java app or by running keytool -delete -alias). Then when I list my keystore again, IFMPROD_SIGN_008 is still there but the cert chain is missing i.e. each cert is shown on its own without the issuing and root CA certs. Using low level tools I can see that these CA certs have been removed.
Now this causes issues when trying to use these entries with e.g. SunJSSE client auth because the server hello message specifies the trusted root but the client hasn't got the full chain in the HSM anymore and bombs the ssl neg.
So I thought well I guess I just need to import each ca cert on its own - except you cant do that with PKCS11 because root CA certs cannot be imported on their own into the HSM using keytool.......
Here I have recreated it using keytool alone using a G&D USB crypto device.
keytool -keystore NONE -storepass 123456 -storetype PKCS11 -list -v
Keystore type: PKCS11
Keystore provider: SunPKCS11-BTHSM
Your keystore contains 2 entries
Alias name: IFMPROD_SIGN_007
Entry type: keyEntry
Certificate chain length: 3
Certificate[1]:
Owner: CN=CUS-GW-2002.intra.ifm.bt.com, OU=MSM, O=SMITHSBANK
Issuer: CN=TESTISSCA, OU=MSM, O=BT
Serial number: 1bc9d9a30000000002e6
Valid from: Fri Apr 30 08:37:17 GMT 2010 until: Sat Apr 30 08:37:17 GMT 2011
Certificate fingerprints:
MD5: 7A:77:2F:64:BB:CA:31:E7:55:5B:4E:8D:04:93:6B:21
SHA1: B5:0D:F5:A7:6F:11:31:12:00:CA:A1:B8:F5:DC:7B:6B:13:CD:68:36
Certificate[2]:
Owner: CN=TESTISSCA, OU=MSM, O=BT......
Issuer: CN=DEVROOTCA, OU=IFM, O=BT Syntegra, L=Fleet, ST=Hants, C=GB, EMAILADDRE
SS=###@###.###
Serial number: 51e90a42000100000012
Valid from: Mon Nov 17 13:48:12 GMT 2008 until: Sun Mar 17 12:18:55 GMT 2024
Certificate fingerprints:
MD5: 66:E1:25:FA:CC:02:74:95:E9:A7:E6:A7:E9:32:DF:F1
SHA1: 07:47:3B:06:FB:11:E9:F5:94:99:1E:6E:7F:67:81:E1:63:A3:46:21
Certificate[3]:
Owner: CN=DEVROOTCA, OU=IFM, O=BT Syntegra, L=Fleet, ST=Hants, C=GB, EMAILADDRES
S=###@###.###
Issuer: CN=DEVROOTCA, OU=IFM, O=BT Syntegra, L=Fleet, ST=Hants, C=GB, EMAILADDRE
SS=###@###.###
Serial number: 5c3ad550252cd1804d9b9d256ed9cbbd
Valid from: Wed Mar 17 12:03:38 GMT 2004 until: Sun Mar 17 12:18:55 GMT 2024
Certificate fingerprints:
MD5: 19:98:5A:49:6F:E6:94:73:B1:06:3F:07:E0:08:F0:D9
SHA1: 28:14:A1:F7:8B:89:2D:1A:A1:AB:AE:C7:17:01:BF:60:06:32:D6:1F
*****************************************
*****************************************
Alias name: IFMPROD_SIGN_008
Entry type: keyEntry
Certificate chain length: 3
Certificate[1]:
Owner: CN=CUS-GW-2002.intra.ifm.bt.com, OU=MSM, O=SMITHSBANK
Issuer: CN=TESTISSCA, OU=MSM, O=BT
Serial number: 1be98fcd0000000002e8
Valid from: Fri Apr 30 09:11:55 GMT 2010 until: Sat Apr 30 09:11:55 GMT 2011
Certificate fingerprints:
MD5: 30:7B:7A:8A:4F:A0:5E:42:87:C6:ED:B3:A9:08:6A:74
SHA1: 82:C9:DB:66:DF:12:DB:5A:ED:46:B9:79:3B:20:68:83:97:8A:57:EC
Certificate[2]:
Owner: CN=TESTISSCA, OU=MSM, O=BT
Issuer: CN=DEVROOTCA, OU=IFM, O=BT Syntegra, L=Fleet, ST=Hants, C=GB, EMAILADDRE
SS=###@###.###
Serial number: 51e90a42000100000012
Valid from: Mon Nov 17 13:48:12 GMT 2008 until: Sun Mar 17 12:18:55 GMT 2024
Certificate fingerprints:
MD5: 66:E1:25:FA:CC:02:74:95:E9:A7:E6:A7:E9:32:DF:F1
SHA1: 07:47:3B:06:FB:11:E9:F5:94:99:1E:6E:7F:67:81:E1:63:A3:46:21
Certificate[3]:
Owner: CN=DEVROOTCA, OU=IFM, O=BT Syntegra, L=Fleet, ST=Hants, C=GB, EMAILADDRES
S=###@###.###
Issuer: CN=DEVROOTCA, OU=IFM, O=BT Syntegra, L=Fleet, ST=Hants, C=GB, EMAILADDRE
SS=###@###.###
Serial number: 5c3ad550252cd1804d9b9d256ed9cbbd
Valid from: Wed Mar 17 12:03:38 GMT 2004 until: Sun Mar 17 12:18:55 GMT 2024
Certificate fingerprints:
MD5: 19:98:5A:49:6F:E6:94:73:B1:06:3F:07:E0:08:F0:D9
SHA1: 28:14:A1:F7:8B:89:2D:1A:A1:AB:AE:C7:17:01:BF:60:06:32:D6:1F
*****************************************
keytool -debug -keystore NONE -storepass 123456 -storetype PKCS11 -delete -alias IFMPROD_SIGN_007
keytool -keystore NONE -storepass 123456 -storetype PKCS11 -list -v
Keystore type: PKCS11
Keystore provider: SunPKCS11-BTHSM
Your keystore contains 1 entry
Alias name: IFMPROD_SIGN_008
Entry type: keyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=CUS-GW-2002.intra.ifm.bt.com, OU=MSM, O=SMITHSBANK
Issuer: CN=TESTISSCA, OU=MSM, O=BT
Serial number: 1be98fcd0000000002e8
Valid from: Fri Apr 30 09:11:55 GMT 2010 until: Sat Apr 30 09:11:55 GMT 2011
Certificate fingerprints:
MD5: 30:7B:7A:8A:4F:A0:5E:42:87:C6:ED:B3:A9:08:6A:74
SHA1: 82:C9:DB:66:DF:12:DB:5A:ED:46:B9:79:3B:20:68:83:97:8A:57:EC
*****************************************
*****************************************
JRE is 1.5.0_22 but 1.6.0_13 also does the same thing.
Iâve looked at openjdk and can see that the code should retain CA certs if they are referenced in the chains of other key entries. What my app does is annually generate new RSA keys and gt them recertified and while thatâs happening the system can continue to use the old key+cert chain until the new one has been issued by the CA and can be loaded. I then import the new entry (as a cert chain) then if that looks good I then remove the old entry. The problem is that by removing the old entry it blows the cert chain away for the new entry and you end up with an unusable key entry.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Obtain a PKCS11 device (password 123456)
Configure SunPKCS11 to use this device.
Configure SunPKCS11 in java,security
Create two key entries RSA and load cert chains issued by the same CA (say alias1 and alias2)
List the device contents to see the two chains:
keytool -keystore NONE -storetype PKCS11 -storepass 123456 -list -v
Delete one of the two aliases
keytool -keystore NONE -storetype PKCS11 -storepass 123456 -delete -alias alias1
List the device contents to see the remaining key entry plus chain:
keytool -keystore NONE -storetype PKCS11 -storepass 123456 -list -v
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
At the end of the steps outlined the keytool listing SHOULD show the remaining entry with a full chain.
ACTUAL -
The keystore listing lists the remaining keystore entry but with the CA certificates missing
ERROR MESSAGES/STACK TRACES THAT OCCUR :
N/A the error is that the cert chain for the remaining key entry is destroyed making use of e.g. JSSE client auth impossible.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
No source code required. Using keytool repeats the problem.
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
I have coded a workaround. My code seeks out a key entry that is a sibling or in some way related to the doomed entry. It then gets this sibling and its chain, removes the doomed entry then stores the entry back in again.
/**
* Delete the given keystore entry.
* Updated 7/5/10: if the key entry has a certificate chain then replace this with a self-cert
* before deleting the entry. The reason for doing this is that the deleteEntry
* takes out the full cert chain regardless of whether or not the cert chain comp[onents are used elsewhere.
* @param alias : doomed alias
* @throws KeyStoreException if not found or cant remove.
*/
public synchronized void deleteAlias(String alias)
throws KeyStoreException
{
boolean deleted = false;
if (_keyStore.containsAlias(alias)) {
try {
if (_keyStore.isKeyEntry(alias)) {
X509Certificate [] certChain = findCertificateChain(alias);
if (certChain != null && certChain.length > 0) {
if (certChain.length > 1) {
// Find another entry that is issued by the same issuer.
CertificateSibling cs = new CertificateSibling();
if (cs.findRelative(alias, certChain)) {
_keyStore.deleteEntry(alias);
deleted = true;
if (cs.keyPair != null && cs.certChain != null) {
storeKeyPair(cs.alias, cs.keyPair, cs.certChain);
}
}
}
}
}
}
// if the self-cert process fails then just delete the entry.
catch (GeneralSecurityException e) {
}
finally {
if (!deleted) {
_keyStore.deleteEntry(alias);
}
}
}
}
public class CertificateSibling {
String alias;
X509Certificate [] certChain;
KeyPair keyPair;
/**
* Find a single sibling entry to the given alias i.e. one that shares the same
* issuer principal
* @param alias : the alias whose siblings are being sought
* @param issuer : the issuer principal
* @return an array of strings or an array of 0 length if none found.
* @throws KeyStoreException : failed to access the keystore.
*/
private boolean findIndexedRelative(String alias, int parentIndex, X509Certificate [] certChain) throws KeyStoreException {
Enumeration<String> eAliases = _keyStore.aliases();
while (eAliases.hasMoreElements()) {
String possibleSliblingAlias = eAliases.nextElement();
if (!possibleSliblingAlias.equalsIgnoreCase(alias)) {
X509Certificate [] siblingCertChain = findCertificateChain(possibleSliblingAlias);
if (siblingCertChain != null && siblingCertChain.length > parentIndex && certChain[parentIndex].equals(siblingCertChain[parentIndex])) {
this.alias = possibleSliblingAlias;
this.keyPair = findKeyPair(possibleSliblingAlias, null);
this.certChain = siblingCertChain;
return true;
}
}
}
return false;
}
/**
* Find a single sibling entry to the given alias i.e. one that shares the same
* issuer principal
* @param alias : the alias whose siblings are being sought
* @param issuer : the issuer principal
* @return an array of strings or an array of 0 length if none found.
* @throws KeyStoreException : failed to access the keystore.
*/
public boolean findRelative(String alias, X509Certificate [] certChain) throws KeyStoreException {
boolean found = false;
if (certChain == null || certChain.length <= 1) {
return false;
}
for (int i = 1; !found && i < certChain.length; i++) {
found = findIndexedRelative(alias, i, certChain);
}
return found;
}
}
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) Client VM (build 11.0-b15, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Windows XP or 2003:
Microsoft Windows XP [Version 5.1.2600]
EXTRA RELEVANT SYSTEM CONFIGURATION :
PKCS11 config file:
name=BTHSM
library=C:\WINDOWS\system32\aetpkss1.dll
description=StarKey_64K_SmartCafe
slotListIndex=1
attributes(generate,CKO_PRIVATE_KEY,CKK_RSA) = {
CKA_TOKEN = true
CKA_SIGN = true
CKA_DECRYPT = true
CKA_SENSITIVE = true
CKA_PRIVATE = true
CKA_EXTRACTABLE = false
CKA_UNWRAP = true
}
attributes(*,CKO_PUBLIC_KEY,CKK_RSA) = {
CKA_ENCRYPT = true
CKA_VERIFY = true
CKA_VERIFY_RECOVER = true
CKA_WRAP = true
}
A DESCRIPTION OF THE PROBLEM :
I think there is a problem with SunPKCS11 KeyStore deleteEntry where it deletes more certs than it should do. I have a keystore with 2 entries:
IFMPROD_SIGN_008
IFMPROD_SIGN_007
all key entries are under the same CA hierarchy (issuing and root CA). I can use keytool to list with verbose and in each case see a nice 3 cert chain for each entry. I then use the deleteAlias to remove IFMPROD_SIGN_007 (either within a Java app or by running keytool -delete -alias). Then when I list my keystore again, IFMPROD_SIGN_008 is still there but the cert chain is missing i.e. each cert is shown on its own without the issuing and root CA certs. Using low level tools I can see that these CA certs have been removed.
Now this causes issues when trying to use these entries with e.g. SunJSSE client auth because the server hello message specifies the trusted root but the client hasn't got the full chain in the HSM anymore and bombs the ssl neg.
So I thought well I guess I just need to import each ca cert on its own - except you cant do that with PKCS11 because root CA certs cannot be imported on their own into the HSM using keytool.......
Here I have recreated it using keytool alone using a G&D USB crypto device.
keytool -keystore NONE -storepass 123456 -storetype PKCS11 -list -v
Keystore type: PKCS11
Keystore provider: SunPKCS11-BTHSM
Your keystore contains 2 entries
Alias name: IFMPROD_SIGN_007
Entry type: keyEntry
Certificate chain length: 3
Certificate[1]:
Owner: CN=CUS-GW-2002.intra.ifm.bt.com, OU=MSM, O=SMITHSBANK
Issuer: CN=TESTISSCA, OU=MSM, O=BT
Serial number: 1bc9d9a30000000002e6
Valid from: Fri Apr 30 08:37:17 GMT 2010 until: Sat Apr 30 08:37:17 GMT 2011
Certificate fingerprints:
MD5: 7A:77:2F:64:BB:CA:31:E7:55:5B:4E:8D:04:93:6B:21
SHA1: B5:0D:F5:A7:6F:11:31:12:00:CA:A1:B8:F5:DC:7B:6B:13:CD:68:36
Certificate[2]:
Owner: CN=TESTISSCA, OU=MSM, O=BT......
Issuer: CN=DEVROOTCA, OU=IFM, O=BT Syntegra, L=Fleet, ST=Hants, C=GB, EMAILADDRE
SS=###@###.###
Serial number: 51e90a42000100000012
Valid from: Mon Nov 17 13:48:12 GMT 2008 until: Sun Mar 17 12:18:55 GMT 2024
Certificate fingerprints:
MD5: 66:E1:25:FA:CC:02:74:95:E9:A7:E6:A7:E9:32:DF:F1
SHA1: 07:47:3B:06:FB:11:E9:F5:94:99:1E:6E:7F:67:81:E1:63:A3:46:21
Certificate[3]:
Owner: CN=DEVROOTCA, OU=IFM, O=BT Syntegra, L=Fleet, ST=Hants, C=GB, EMAILADDRES
S=###@###.###
Issuer: CN=DEVROOTCA, OU=IFM, O=BT Syntegra, L=Fleet, ST=Hants, C=GB, EMAILADDRE
SS=###@###.###
Serial number: 5c3ad550252cd1804d9b9d256ed9cbbd
Valid from: Wed Mar 17 12:03:38 GMT 2004 until: Sun Mar 17 12:18:55 GMT 2024
Certificate fingerprints:
MD5: 19:98:5A:49:6F:E6:94:73:B1:06:3F:07:E0:08:F0:D9
SHA1: 28:14:A1:F7:8B:89:2D:1A:A1:AB:AE:C7:17:01:BF:60:06:32:D6:1F
*****************************************
*****************************************
Alias name: IFMPROD_SIGN_008
Entry type: keyEntry
Certificate chain length: 3
Certificate[1]:
Owner: CN=CUS-GW-2002.intra.ifm.bt.com, OU=MSM, O=SMITHSBANK
Issuer: CN=TESTISSCA, OU=MSM, O=BT
Serial number: 1be98fcd0000000002e8
Valid from: Fri Apr 30 09:11:55 GMT 2010 until: Sat Apr 30 09:11:55 GMT 2011
Certificate fingerprints:
MD5: 30:7B:7A:8A:4F:A0:5E:42:87:C6:ED:B3:A9:08:6A:74
SHA1: 82:C9:DB:66:DF:12:DB:5A:ED:46:B9:79:3B:20:68:83:97:8A:57:EC
Certificate[2]:
Owner: CN=TESTISSCA, OU=MSM, O=BT
Issuer: CN=DEVROOTCA, OU=IFM, O=BT Syntegra, L=Fleet, ST=Hants, C=GB, EMAILADDRE
SS=###@###.###
Serial number: 51e90a42000100000012
Valid from: Mon Nov 17 13:48:12 GMT 2008 until: Sun Mar 17 12:18:55 GMT 2024
Certificate fingerprints:
MD5: 66:E1:25:FA:CC:02:74:95:E9:A7:E6:A7:E9:32:DF:F1
SHA1: 07:47:3B:06:FB:11:E9:F5:94:99:1E:6E:7F:67:81:E1:63:A3:46:21
Certificate[3]:
Owner: CN=DEVROOTCA, OU=IFM, O=BT Syntegra, L=Fleet, ST=Hants, C=GB, EMAILADDRES
S=###@###.###
Issuer: CN=DEVROOTCA, OU=IFM, O=BT Syntegra, L=Fleet, ST=Hants, C=GB, EMAILADDRE
SS=###@###.###
Serial number: 5c3ad550252cd1804d9b9d256ed9cbbd
Valid from: Wed Mar 17 12:03:38 GMT 2004 until: Sun Mar 17 12:18:55 GMT 2024
Certificate fingerprints:
MD5: 19:98:5A:49:6F:E6:94:73:B1:06:3F:07:E0:08:F0:D9
SHA1: 28:14:A1:F7:8B:89:2D:1A:A1:AB:AE:C7:17:01:BF:60:06:32:D6:1F
*****************************************
keytool -debug -keystore NONE -storepass 123456 -storetype PKCS11 -delete -alias IFMPROD_SIGN_007
keytool -keystore NONE -storepass 123456 -storetype PKCS11 -list -v
Keystore type: PKCS11
Keystore provider: SunPKCS11-BTHSM
Your keystore contains 1 entry
Alias name: IFMPROD_SIGN_008
Entry type: keyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=CUS-GW-2002.intra.ifm.bt.com, OU=MSM, O=SMITHSBANK
Issuer: CN=TESTISSCA, OU=MSM, O=BT
Serial number: 1be98fcd0000000002e8
Valid from: Fri Apr 30 09:11:55 GMT 2010 until: Sat Apr 30 09:11:55 GMT 2011
Certificate fingerprints:
MD5: 30:7B:7A:8A:4F:A0:5E:42:87:C6:ED:B3:A9:08:6A:74
SHA1: 82:C9:DB:66:DF:12:DB:5A:ED:46:B9:79:3B:20:68:83:97:8A:57:EC
*****************************************
*****************************************
JRE is 1.5.0_22 but 1.6.0_13 also does the same thing.
Iâve looked at openjdk and can see that the code should retain CA certs if they are referenced in the chains of other key entries. What my app does is annually generate new RSA keys and gt them recertified and while thatâs happening the system can continue to use the old key+cert chain until the new one has been issued by the CA and can be loaded. I then import the new entry (as a cert chain) then if that looks good I then remove the old entry. The problem is that by removing the old entry it blows the cert chain away for the new entry and you end up with an unusable key entry.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Obtain a PKCS11 device (password 123456)
Configure SunPKCS11 to use this device.
Configure SunPKCS11 in java,security
Create two key entries RSA and load cert chains issued by the same CA (say alias1 and alias2)
List the device contents to see the two chains:
keytool -keystore NONE -storetype PKCS11 -storepass 123456 -list -v
Delete one of the two aliases
keytool -keystore NONE -storetype PKCS11 -storepass 123456 -delete -alias alias1
List the device contents to see the remaining key entry plus chain:
keytool -keystore NONE -storetype PKCS11 -storepass 123456 -list -v
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
At the end of the steps outlined the keytool listing SHOULD show the remaining entry with a full chain.
ACTUAL -
The keystore listing lists the remaining keystore entry but with the CA certificates missing
ERROR MESSAGES/STACK TRACES THAT OCCUR :
N/A the error is that the cert chain for the remaining key entry is destroyed making use of e.g. JSSE client auth impossible.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
No source code required. Using keytool repeats the problem.
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
I have coded a workaround. My code seeks out a key entry that is a sibling or in some way related to the doomed entry. It then gets this sibling and its chain, removes the doomed entry then stores the entry back in again.
/**
* Delete the given keystore entry.
* Updated 7/5/10: if the key entry has a certificate chain then replace this with a self-cert
* before deleting the entry. The reason for doing this is that the deleteEntry
* takes out the full cert chain regardless of whether or not the cert chain comp[onents are used elsewhere.
* @param alias : doomed alias
* @throws KeyStoreException if not found or cant remove.
*/
public synchronized void deleteAlias(String alias)
throws KeyStoreException
{
boolean deleted = false;
if (_keyStore.containsAlias(alias)) {
try {
if (_keyStore.isKeyEntry(alias)) {
X509Certificate [] certChain = findCertificateChain(alias);
if (certChain != null && certChain.length > 0) {
if (certChain.length > 1) {
// Find another entry that is issued by the same issuer.
CertificateSibling cs = new CertificateSibling();
if (cs.findRelative(alias, certChain)) {
_keyStore.deleteEntry(alias);
deleted = true;
if (cs.keyPair != null && cs.certChain != null) {
storeKeyPair(cs.alias, cs.keyPair, cs.certChain);
}
}
}
}
}
}
// if the self-cert process fails then just delete the entry.
catch (GeneralSecurityException e) {
}
finally {
if (!deleted) {
_keyStore.deleteEntry(alias);
}
}
}
}
public class CertificateSibling {
String alias;
X509Certificate [] certChain;
KeyPair keyPair;
/**
* Find a single sibling entry to the given alias i.e. one that shares the same
* issuer principal
* @param alias : the alias whose siblings are being sought
* @param issuer : the issuer principal
* @return an array of strings or an array of 0 length if none found.
* @throws KeyStoreException : failed to access the keystore.
*/
private boolean findIndexedRelative(String alias, int parentIndex, X509Certificate [] certChain) throws KeyStoreException {
Enumeration<String> eAliases = _keyStore.aliases();
while (eAliases.hasMoreElements()) {
String possibleSliblingAlias = eAliases.nextElement();
if (!possibleSliblingAlias.equalsIgnoreCase(alias)) {
X509Certificate [] siblingCertChain = findCertificateChain(possibleSliblingAlias);
if (siblingCertChain != null && siblingCertChain.length > parentIndex && certChain[parentIndex].equals(siblingCertChain[parentIndex])) {
this.alias = possibleSliblingAlias;
this.keyPair = findKeyPair(possibleSliblingAlias, null);
this.certChain = siblingCertChain;
return true;
}
}
}
return false;
}
/**
* Find a single sibling entry to the given alias i.e. one that shares the same
* issuer principal
* @param alias : the alias whose siblings are being sought
* @param issuer : the issuer principal
* @return an array of strings or an array of 0 length if none found.
* @throws KeyStoreException : failed to access the keystore.
*/
public boolean findRelative(String alias, X509Certificate [] certChain) throws KeyStoreException {
boolean found = false;
if (certChain == null || certChain.length <= 1) {
return false;
}
for (int i = 1; !found && i < certChain.length; i++) {
found = findIndexedRelative(alias, i, certChain);
}
return found;
}
}