下面列出了java.security.KeyStore#PrivateKeyEntry ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private static void check(String encodedBlob) throws Exception {
byte[] blob = new byte[encodedBlob.length() * 2];
for (int i = 0; i < blob.length; ) {
final char ch = encodedBlob.charAt(i / 2);
blob[i++] = (byte) (ch >> 8);
blob[i++] = (byte) ch;
}
KeyStore store = KeyStore.getInstance("PKCS12");
store.load(new ByteArrayInputStream(blob), new char[0]);
if (!store.aliases().nextElement().equals("test"))
throw new Exception("test alias not found");
KeyStore.PrivateKeyEntry e =
(KeyStore.PrivateKeyEntry) store.getEntry("test",
new KeyStore.PasswordProtection(new char[0]));
X509Certificate cert = (X509Certificate) e.getCertificateChain()[0];
if (!cert.getSubjectDN().toString().equals("CN=Test Key"))
throw new Exception("invalid certificate subject DN");
RSAPrivateCrtKey key = (RSAPrivateCrtKey) e.getPrivateKey();
if (!key.getPublicExponent().equals(BigInteger.valueOf(65537)))
throw new Exception("invalid public exponent");
}
private void runTest() throws IOException, KeyStoreException,
NoSuchAlgorithmException, CertificateException,
UnrecoverableKeyException {
KeyStore ks = Utils.loadKeyStore(KEYSTORE_PATH,
Utils.KeyStoreType.pkcs12, PASSWORD);
Key key = ks.getKey(ALIAS, PASSWORD);
Certificate cert = ks
.getCertificate(ALIAS);
KeyStore.Entry entry = new KeyStore.PrivateKeyEntry(
(PrivateKey) key,
new Certificate[]{cert});
if (!entry.getAttributes().isEmpty()) {
throw new RuntimeException("Entry's attributes set "
+ "must be empty");
}
out.println("Test Passed");
}
@Test
public void shouldDeleteAESKeysAndThrowOnBadPaddingExceptionWhenTryingToRSADecrypt() throws Exception {
exception.expect(CryptoException.class);
exception.expectMessage("The RSA encrypted input is corrupted and cannot be recovered. Please discard it.");
PrivateKey privateKey = PowerMockito.mock(PrivateKey.class);
KeyStore.PrivateKeyEntry privateKeyEntry = PowerMockito.mock(KeyStore.PrivateKeyEntry.class);
doReturn(privateKey).when(privateKeyEntry).getPrivateKey();
doReturn(privateKeyEntry).when(cryptoUtil).getRSAKeyEntry();
doThrow(new BadPaddingException()).when(rsaCipher).doFinal(any(byte[].class));
cryptoUtil.RSADecrypt(new byte[0]);
Mockito.verify(keyStore, never()).deleteEntry(KEY_ALIAS);
Mockito.verify(storage).remove(KEY_ALIAS);
Mockito.verify(storage).remove(KEY_ALIAS + "_iv");
}
private static void check(String encodedBlob) throws Exception {
byte[] blob = new byte[encodedBlob.length() * 2];
for (int i = 0; i < blob.length; ) {
final char ch = encodedBlob.charAt(i / 2);
blob[i++] = (byte) (ch >> 8);
blob[i++] = (byte) ch;
}
KeyStore store = KeyStore.getInstance("PKCS12");
store.load(new ByteArrayInputStream(blob), new char[0]);
if (!store.aliases().nextElement().equals("test"))
throw new Exception("test alias not found");
KeyStore.PrivateKeyEntry e =
(KeyStore.PrivateKeyEntry) store.getEntry("test",
new KeyStore.PasswordProtection(new char[0]));
X509Certificate cert = (X509Certificate) e.getCertificateChain()[0];
if (!cert.getSubjectDN().toString().equals("CN=Test Key"))
throw new Exception("invalid certificate subject DN");
RSAPrivateCrtKey key = (RSAPrivateCrtKey) e.getPrivateKey();
if (!key.getPublicExponent().equals(BigInteger.valueOf(65537)))
throw new Exception("invalid public exponent");
}
@Test
public void shouldDeleteAESKeysAndThrowOnIllegalBlockSizeExceptionWhenTryingToRSAEncrypt() throws Exception {
exception.expect(CryptoException.class);
exception.expectMessage("The RSA decrypted input is invalid.");
Certificate certificate = PowerMockito.mock(Certificate.class);
KeyStore.PrivateKeyEntry privateKeyEntry = PowerMockito.mock(KeyStore.PrivateKeyEntry.class);
doReturn(certificate).when(privateKeyEntry).getCertificate();
doReturn(privateKeyEntry).when(cryptoUtil).getRSAKeyEntry();
PowerMockito.mockStatic(Cipher.class);
PowerMockito.when(Cipher.getInstance(RSA_TRANSFORMATION)).thenReturn(rsaCipher);
PowerMockito.when(rsaCipher.doFinal(any(byte[].class))).thenThrow(new IllegalBlockSizeException());
cryptoUtil.RSAEncrypt(new byte[0]);
Mockito.verify(keyStore, never()).deleteEntry(KEY_ALIAS);
Mockito.verify(storage).remove(KEY_ALIAS);
Mockito.verify(storage).remove(KEY_ALIAS + "_iv");
}
private void storeAttrs() throws UnrecoverableEntryException,
GeneralSecurityException, NoSuchAlgorithmException,
KeyStoreException, IOException {
KeyStore ksIn = Utils.loadKeyStore(KEYSTORE_PATH,
Utils.KeyStoreType.pkcs12, PASSWORD);
KeyStore ksAttr = KeyStore
.getInstance(Utils.KeyStoreType.pkcs12.name());
ksAttr.load(null);
Key key = ksIn.getKey(ALIAS, PASSWORD);
Certificate cert = ksIn.getCertificate(ALIAS);
Set<KeyStore.Entry.Attribute> attrs =
new HashSet<>(Arrays.asList(ATTR_SET));
KeyStore.Entry e = new KeyStore.PrivateKeyEntry((PrivateKey) key,
new Certificate[]{cert}, attrs);
ksAttr.setEntry(ALIAS, e, new KeyStore.PasswordProtection(
KEY_PASSWORD));
out.println("Attributes before store:");
e.getAttributes().stream().forEach((attr) -> {
out.println(attr.getName() + ", '" + attr.getValue() + "'");
});
Utils.saveKeyStore(ksAttr, WORKING_DIRECTORY + File.separator
+ KESTORE_NEW, PASSWORD);
}
/**
* Helper method compatible with older Android versions to load the Private Key Entry from
* the KeyStore using the {@link #KEY_ALIAS}.
*
* @param keyStore the KeyStore instance. Must be initialized (loaded).
* @return the key entry stored in the KeyStore or null if not present.
* @throws KeyStoreException if the keystore was not initialized.
* @throws NoSuchAlgorithmException if device is not compatible with RSA algorithm. RSA is available since API 18.
* @throws UnrecoverableEntryException if key cannot be recovered. Probably because it was invalidated by a Lock Screen change.
*/
private KeyStore.PrivateKeyEntry getKeyEntryCompat(KeyStore keyStore) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
return (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null);
}
//Following code is for API 28+
PrivateKey privateKey = (PrivateKey) keyStore.getKey(KEY_ALIAS, null);
if (privateKey == null) {
return (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null);
}
Certificate certificate = keyStore.getCertificate(KEY_ALIAS);
if (certificate == null) {
return null;
}
return new KeyStore.PrivateKeyEntry(privateKey, new Certificate[]{certificate});
}
/**
* Determines if the keystore {@code Entry} for the specified
* {@code alias} is an instance or subclass of the specified
* {@code entryClass}.
*
* @param alias the alias name
* @param entryClass the entry class
*
* @return true if the keystore {@code Entry} for the specified
* {@code alias} is an instance or subclass of the
* specified {@code entryClass}, false otherwise
*
* @since 1.5
*/
public boolean
engineEntryInstanceOf(String alias,
Class<? extends KeyStore.Entry> entryClass)
{
if (entryClass == KeyStore.TrustedCertificateEntry.class) {
return engineIsCertificateEntry(alias);
}
if (entryClass == KeyStore.PrivateKeyEntry.class) {
return engineIsKeyEntry(alias) &&
engineGetCertificate(alias) != null;
}
if (entryClass == KeyStore.SecretKeyEntry.class) {
return engineIsKeyEntry(alias) &&
engineGetCertificate(alias) == null;
}
return false;
}
private byte[] rsaEncrypt(
@NonNull Context context,
byte[] secret,
String keystoreAlias
) throws Exception {
final KeyStore keyStore = loadKeyStore();
generateKeyIfNecessary(context, keyStore, keystoreAlias, false);
final KeyStore.PrivateKeyEntry privateKeyEntry
= (KeyStore.PrivateKeyEntry) keyStore.getEntry(keystoreAlias, null);
final Cipher inputCipher = Cipher.getInstance(RSA_MODE, PROVIDER);
inputCipher.init(Cipher.ENCRYPT_MODE, privateKeyEntry.getCertificate().getPublicKey());
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
final CipherOutputStream cipherOutputStream
= new CipherOutputStream(outputStream, inputCipher);
cipherOutputStream.write(secret);
cipherOutputStream.close();
final byte[] vals = outputStream.toByteArray();
return vals;
}
private <T> T signJAXBObject(T jaxbObj) {
DOMResult domResult = new DOMResult();
JAXB.marshal(jaxbObj, domResult);
Document doc = ((Document) domResult.getNode());
Element docElement = doc.getDocumentElement();
try {
KeyStore ks = KeyStore.getInstance(SIGNATURE_KEYSTORE_TYPE);
URL url = Thread.currentThread().getContextClassLoader().getResource(SIGNATURE_KEYSTORE);
ks.load(url.openStream(), SIGNATURE_KEYSTORE_PASSWORD.toCharArray());
KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(SIGNATURE_KEYSTORE_ALIAS, new KeyStore.PasswordProtection(SIGNATURE_KEYSTORE_PASSWORD.toCharArray()));
PrivateKey privateKey = keyEntry.getPrivateKey();
Certificate origCert = keyEntry.getCertificate();
PublicKey validatingKey = origCert.getPublicKey();
TckSigningUtil.signDOM(docElement, privateKey, origCert);
DOMSource domSource = new DOMSource(doc);
T result = (T) JAXB.unmarshal(domSource, jaxbObj.getClass());
return result;
} catch (Exception e) {
throw new RuntimeException("Signature failure due to: " + e.getMessage(), e);
}
}
private String fetchCertificateText(KeyStore.PrivateKeyEntry keystoreEntry) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableEntryException {
X509Certificate certificate = (X509Certificate) keystoreEntry.getCertificate();
Base64 encoder = new Base64(64);
String certificateText = new String(encoder.encode(certificate.getEncoded()));
return certificateText;
}
@Test
public void shouldCreateAESKeyIfStoredOneIsEmpty() throws BadPaddingException, IllegalBlockSizeException {
String emptyString = "";
byte[] sampleBytes = emptyString.getBytes();
byte[] sampleOutput = new byte[]{99, 33, 11};
PowerMockito.mockStatic(Base64.class);
PowerMockito.when(Base64.decode(emptyString, Base64.DEFAULT)).thenReturn(sampleBytes);
PowerMockito.when(Base64.encode(sampleBytes, Base64.DEFAULT)).thenReturn("data".getBytes());
PowerMockito.when(storage.retrieveString(KEY_ALIAS)).thenReturn(emptyString);
doReturn(sampleBytes).when(cryptoUtil).RSAEncrypt(sampleBytes);
//Assume RSAKeyEntry exists
PrivateKey privateKey = PowerMockito.mock(PrivateKey.class);
KeyStore.PrivateKeyEntry privateKeyEntry = PowerMockito.mock(KeyStore.PrivateKeyEntry.class);
doReturn(privateKey).when(privateKeyEntry).getPrivateKey();
doReturn(privateKeyEntry).when(cryptoUtil).getRSAKeyEntry();
doReturn(sampleOutput).when(rsaCipher).doFinal(sampleBytes);
SecretKey secretKey = PowerMockito.mock(SecretKey.class);
PowerMockito.when(secretKey.getEncoded()).thenReturn(sampleBytes);
PowerMockito.when(keyGenerator.generateKey()).thenReturn(secretKey);
final byte[] aesKey = cryptoUtil.getAESKey();
Mockito.verify(keyGenerator).init(256);
Mockito.verify(keyGenerator).generateKey();
Mockito.verify(storage).store(KEY_ALIAS, "data");
assertThat(aesKey, is(notNullValue()));
assertThat(aesKey, is(sampleBytes));
}
@Test
public void shouldThrowOnNoSuchPaddingExceptionWhenTryingToRSADecrypt() throws Exception {
exception.expect(IncompatibleDeviceException.class);
exception.expectMessage("The device is not compatible with the CryptoUtil class");
PrivateKey privateKey = PowerMockito.mock(PrivateKey.class);
KeyStore.PrivateKeyEntry privateKeyEntry = PowerMockito.mock(KeyStore.PrivateKeyEntry.class);
doReturn(privateKey).when(privateKeyEntry).getPrivateKey();
doReturn(privateKeyEntry).when(cryptoUtil).getRSAKeyEntry();
PowerMockito.mockStatic(Cipher.class);
PowerMockito.when(Cipher.getInstance(RSA_TRANSFORMATION)).thenThrow(new NoSuchPaddingException());
cryptoUtil.RSADecrypt(new byte[0]);
}
public byte[] decrypt(String keyAlias, byte[] dataToDecrypt) throws GeneralSecurityException, IOException {
if (!secureKeyStore.hasKeyPair(keyAlias)) {
throw new GeneralSecurityException("missing key " + keyAlias);
}
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) secureKeyStore.getKeyPairEntry(keyAlias);
return RsaHelper.decrypt(secureKeyStore.getSupportedRSAMode(), privateKeyEntry, dataToDecrypt);
}
/**
* {@inheritDoc}
*/
@Override
public void encrypt(String alias, String value) {
KeyStore.Entry entry = getKeyStoreEntry(true, alias);
if (entry == null) {
throw new CryptoFailedException("Unable to generate key for alias " + alias);
}
KeyStore.PrivateKeyEntry key = (KeyStore.PrivateKeyEntry) entry;
byte[] encryptedData = encryptData(alias, value, key.getCertificate().getPublicKey());
storage.saveKeyBytes(alias, encryptedData);
}
private static int copy(int testnum) throws Exception {
if (ks == null) {
ks = KeyStore.getInstance(KS_TYPE, provider);
ks.load(null, tokenPwd);
}
KeyFactory kf = KeyFactory.getInstance("RSA", provider);
PrivateKey pkSession = (PrivateKey)kf.translateKey(pk3);
System.out.println("pkSession = " + pkSession);
ks.setKeyEntry("pkSession", pkSession, null, chain3);
KeyStore.PrivateKeyEntry pke =
(KeyStore.PrivateKeyEntry)ks.getEntry("pkSession", null);
System.out.println("pkSession = " + pke.getPrivateKey());
Certificate[] chain = pke.getCertificateChain();
if (chain.length != chain3.length) {
throw new SecurityException("received chain not correct length");
}
for (int i = 0; i < chain.length; i++) {
if (!chain[i].equals(chain3[i])) {
throw new SecurityException("received chain not equal");
}
}
System.out.println("test " + testnum++ + " passed");
return testnum;
}
/**
* Gets a <code>KeyStore.Entry</code> for the specified alias
* with the specified protection parameter.
*
* @param alias get the <code>KeyStore.Entry</code> for this alias
* @param protParam the <code>ProtectionParameter</code>
* used to protect the <code>Entry</code>,
* which may be <code>null</code>
*
* @return the <code>KeyStore.Entry</code> for the specified alias,
* or <code>null</code> if there is no such entry
*
* @exception KeyStoreException if the operation failed
* @exception NoSuchAlgorithmException if the algorithm for recovering the
* entry cannot be found
* @exception UnrecoverableEntryException if the specified
* <code>protParam</code> were insufficient or invalid
* @exception UnrecoverableKeyException if the entry is a
* <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code>
* and the specified <code>protParam</code> does not contain
* the information needed to recover the key (e.g. wrong password)
*
* @since 1.5
*/
@Override
public KeyStore.Entry engineGetEntry(String alias,
KeyStore.ProtectionParameter protParam)
throws KeyStoreException, NoSuchAlgorithmException,
UnrecoverableEntryException {
if (!engineContainsAlias(alias)) {
return null;
}
Entry entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
if (protParam == null) {
if (engineIsCertificateEntry(alias)) {
if (entry instanceof CertEntry &&
((CertEntry) entry).trustedKeyUsage != null) {
if (debug != null) {
debug.println("Retrieved a trusted certificate at " +
"alias '" + alias + "'");
}
return new KeyStore.TrustedCertificateEntry(
((CertEntry)entry).cert, getAttributes(entry));
}
} else {
throw new UnrecoverableKeyException
("requested entry requires a password");
}
}
if (protParam instanceof KeyStore.PasswordProtection) {
if (engineIsCertificateEntry(alias)) {
throw new UnsupportedOperationException
("trusted certificate entries are not password-protected");
} else if (engineIsKeyEntry(alias)) {
KeyStore.PasswordProtection pp =
(KeyStore.PasswordProtection)protParam;
char[] password = pp.getPassword();
Key key = engineGetKey(alias, password);
if (key instanceof PrivateKey) {
Certificate[] chain = engineGetCertificateChain(alias);
return new KeyStore.PrivateKeyEntry((PrivateKey)key, chain,
getAttributes(entry));
} else if (key instanceof SecretKey) {
return new KeyStore.SecretKeyEntry((SecretKey)key,
getAttributes(entry));
}
} else if (!engineIsKeyEntry(alias)) {
throw new UnsupportedOperationException
("untrusted certificate entries are not " +
"password-protected");
}
}
throw new UnsupportedOperationException();
}
/**
* Given some data and a signature, uses the key pair stored in the Android Key Store to verify
* that the data was signed by this application, using that key pair.
* @param input The data to be verified.
* @param signatureStr The signature provided for the data.
* @return A boolean value telling you whether the signature is valid or not.
*/
public boolean verifyData(String input, String signatureStr) throws KeyStoreException,
CertificateException, NoSuchAlgorithmException, IOException,
UnrecoverableEntryException, InvalidKeyException, SignatureException {
byte[] data = input.getBytes();
byte[] signature;
// BEGIN_INCLUDE(decode_signature)
// Make sure the signature string exists. If not, bail out, nothing to do.
if (signatureStr == null) {
Log.w(TAG, "Invalid signature.");
Log.w(TAG, "Exiting verifyData()...");
return false;
}
try {
// The signature is going to be examined as a byte array,
// not as a base64 encoded string.
signature = Base64.decode(signatureStr, Base64.DEFAULT);
} catch (IllegalArgumentException e) {
// signatureStr wasn't null, but might not have been encoded properly.
// It's not a valid Base64 string.
return false;
}
// END_INCLUDE(decode_signature)
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
// Weird artifact of Java API. If you don't have an InputStream to load, you still need
// to call "load", or it'll crash.
ks.load(null);
// Load the key pair from the Android Key Store
KeyStore.Entry entry = ks.getEntry(mAlias, null);
if (entry == null) {
Log.w(TAG, "No key found under alias: " + mAlias);
Log.w(TAG, "Exiting verifyData()...");
return false;
}
if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
Log.w(TAG, "Not an instance of a PrivateKeyEntry");
return false;
}
// This class doesn't actually represent the signature,
// just the engine for creating/verifying signatures, using
// the specified algorithm.
Signature s = Signature.getInstance(SecurityConstants.SIGNATURE_SHA256withRSA);
// BEGIN_INCLUDE(verify_data)
// Verify the data.
s.initVerify(((KeyStore.PrivateKeyEntry) entry).getCertificate());
s.update(data);
return s.verify(signature);
// END_INCLUDE(verify_data)
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Test
@Config(sdk = 23)
public void shouldCreateRSAKeyPairIfMissingOnAPI23AndUp() throws Exception {
ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", 23);
PowerMockito.when(keyStore.containsAlias(KEY_ALIAS)).thenReturn(false);
KeyStore.PrivateKeyEntry expectedEntry = PowerMockito.mock(KeyStore.PrivateKeyEntry.class);
PowerMockito.when(keyStore.getEntry(KEY_ALIAS, null)).thenReturn(expectedEntry);
KeyGenParameterSpec spec = PowerMockito.mock(KeyGenParameterSpec.class);
KeyGenParameterSpec.Builder builder = newKeyGenParameterSpecBuilder(spec);
PowerMockito.whenNew(KeyGenParameterSpec.Builder.class).withArguments(KEY_ALIAS, KeyProperties.PURPOSE_DECRYPT | KeyProperties.PURPOSE_ENCRYPT).thenReturn(builder);
ArgumentCaptor<X500Principal> principalCaptor = ArgumentCaptor.forClass(X500Principal.class);
ArgumentCaptor<Date> startDateCaptor = ArgumentCaptor.forClass(Date.class);
ArgumentCaptor<Date> endDateCaptor = ArgumentCaptor.forClass(Date.class);
final KeyStore.PrivateKeyEntry entry = cryptoUtil.getRSAKeyEntry();
Mockito.verify(builder).setKeySize(2048);
Mockito.verify(builder).setCertificateSubject(principalCaptor.capture());
Mockito.verify(builder).setCertificateSerialNumber(BigInteger.ONE);
Mockito.verify(builder).setCertificateNotBefore(startDateCaptor.capture());
Mockito.verify(builder).setCertificateNotAfter(endDateCaptor.capture());
Mockito.verify(builder).setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1);
Mockito.verify(builder).setBlockModes(KeyProperties.BLOCK_MODE_ECB);
Mockito.verify(keyPairGenerator).initialize(spec);
Mockito.verify(keyPairGenerator).generateKeyPair();
assertThat(principalCaptor.getValue(), is(notNullValue()));
assertThat(principalCaptor.getValue().getName(), is(CERTIFICATE_PRINCIPAL));
assertThat(startDateCaptor.getValue(), is(notNullValue()));
long diffMillis = startDateCaptor.getValue().getTime() - new Date().getTime();
long days = TimeUnit.MILLISECONDS.toDays(diffMillis);
assertThat(days, is(0L)); //Date is Today
assertThat(endDateCaptor.getValue(), is(notNullValue()));
diffMillis = endDateCaptor.getValue().getTime() - new Date().getTime();
days = TimeUnit.MILLISECONDS.toDays(diffMillis);
assertThat(days, is(greaterThan(25 * 365L))); //Date more than 25 Years in days
assertThat(entry, is(expectedEntry));
}
/**
* Gets a <code>KeyStore.Entry</code> for the specified alias
* with the specified protection parameter.
*
* @param alias get the <code>KeyStore.Entry</code> for this alias
* @param protParam the <code>ProtectionParameter</code>
* used to protect the <code>Entry</code>,
* which may be <code>null</code>
*
* @return the <code>KeyStore.Entry</code> for the specified alias,
* or <code>null</code> if there is no such entry
*
* @exception KeyStoreException if the operation failed
* @exception NoSuchAlgorithmException if the algorithm for recovering the
* entry cannot be found
* @exception UnrecoverableEntryException if the specified
* <code>protParam</code> were insufficient or invalid
* @exception UnrecoverableKeyException if the entry is a
* <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code>
* and the specified <code>protParam</code> does not contain
* the information needed to recover the key (e.g. wrong password)
*
* @since 1.5
*/
@Override
public KeyStore.Entry engineGetEntry(String alias,
KeyStore.ProtectionParameter protParam)
throws KeyStoreException, NoSuchAlgorithmException,
UnrecoverableEntryException {
if (!engineContainsAlias(alias)) {
return null;
}
Entry entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
if (protParam == null) {
if (engineIsCertificateEntry(alias)) {
if (entry instanceof CertEntry &&
((CertEntry) entry).trustedKeyUsage != null) {
if (debug != null) {
debug.println("Retrieved a trusted certificate at " +
"alias '" + alias + "'");
}
return new KeyStore.TrustedCertificateEntry(
((CertEntry)entry).cert, getAttributes(entry));
}
} else {
throw new UnrecoverableKeyException
("requested entry requires a password");
}
}
if (protParam instanceof KeyStore.PasswordProtection) {
if (engineIsCertificateEntry(alias)) {
throw new UnsupportedOperationException
("trusted certificate entries are not password-protected");
} else if (engineIsKeyEntry(alias)) {
KeyStore.PasswordProtection pp =
(KeyStore.PasswordProtection)protParam;
char[] password = pp.getPassword();
Key key = engineGetKey(alias, password);
if (key instanceof PrivateKey) {
Certificate[] chain = engineGetCertificateChain(alias);
return new KeyStore.PrivateKeyEntry((PrivateKey)key, chain,
getAttributes(entry));
} else if (key instanceof SecretKey) {
return new KeyStore.SecretKeyEntry((SecretKey)key,
getAttributes(entry));
}
} else if (!engineIsKeyEntry(alias)) {
throw new UnsupportedOperationException
("untrusted certificate entries are not " +
"password-protected");
}
}
throw new UnsupportedOperationException();
}