com.unbound.provider.UBKeyStore Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of unbound-java-provider Show documentation
Show all versions of unbound-java-provider Show documentation
This is a collection of JAVA libraries that implement Unbound cryptographic classes for JAVA provider, PKCS11 wrapper, cryptoki, and advapi
package com.unbound.provider;
import com.dyadicsec.provider.DYCryptoProvider;
import com.unbound.common.Log;
import com.unbound.provider.kmip.KMIP;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.time.Clock;
import java.util.*;
public final class UBKeyStore extends KeyStoreSpi
{
private static final int CACHE_TIMEOUT = 30000; // milliseconds
private static final Clock clock = Clock.systemUTC();
static final class Entry
{
UBPrivateKey prvKey = null;
UBCertificate cert = null;
Certificate[] chain = null;
UBSecretKey secretKey = null;
Entry(UBPrivateKey key, UBCertificate cert, Certificate[] chain) throws InvalidKeySpecException, CertificateException, IOException
{
this.prvKey = key;
this.cert = cert;
if (chain==null) chain = cert.getChain();
this.chain = chain;
}
Entry(UBPrivateKey key) // orphan
{
this.prvKey = key;
}
Entry(UBCertificate cert)
{
this.cert = cert;
}
Entry(UBSecretKey secret)
{
this.secretKey = secret;
}
String getName()
{
if (secretKey !=null) return secretKey.name;
return isTrustedCert() ? cert.name : prvKey.name;
}
boolean isTrustedCert()
{
return prvKey == null && secretKey == null;
}
boolean isOrphanPrvKey()
{
return prvKey != null && cert == null;
}
}
private Partition partition;
private Map cache = new HashMap<>();
private long lastCacheClock = 0;
UBKeyStore(Partition partition)
{
this.partition = partition;
}
private Entry findEntry(String alias) throws InvalidKeySpecException, CertificateException, IOException
{
Entry entry = null;
Log log = Log.func("UBKeyStore.findEntry").log("alias", alias).end(); try
{
synchronized (this)
{
entry = cache.get(alias.toUpperCase());
}
if (entry!=null) return entry;
UBPrivateKey key = UBPrivateKey.locate(partition, 0, alias);
if (key==null)
{
UBCertificate cert = UBCertificate.locate(partition, alias);
if (cert!=null) entry = new Entry(cert);
else
{
UBSecretKey secret = UBSecretKey.locate(partition, alias);
if (secret==null) return null;
entry = new Entry(secret);
}
}
else
{
UBCertificate cert = UBCertificate.locateByKeyUid(partition, key.uid);
if (cert==null) entry = new Entry(key);
else entry = new Entry(key, cert, null);
}
synchronized (this)
{
cache.put(entry.getName().toUpperCase(), entry);
}
if (!UBCryptoProvider.allowedPrivateKeyWithoutCertificate && entry!=null && entry.isOrphanPrvKey()) entry = null;
return entry;
}
catch (Exception e) { log.failed(e); throw e; }
finally
{
log = log.leavePrint();
if (entry!=null) log.log("entry", entry.getName());
log.end();
}
}
private final static class FilteredAliases implements Enumeration
{
private Iterator< Map.Entry > it;
private Map.Entry next = null;
FilteredAliases(Map map) { this.it = map.entrySet().iterator(); }
private void findNext()
{
if (next != null) return;
while (it.hasNext())
{
Map.Entry element = it.next();
if (element.getValue().isOrphanPrvKey()) continue;
next = element;
break;
}
}
public boolean hasMoreElements()
{
findNext();
return next != null;
}
public String nextElement() throws NoSuchElementException
{
findNext();
if (next == null) throw new NoSuchElementException();
String result = next.getKey();
next = null;
return result;
}
}
private Enumeration getAliases()
{
if (UBCryptoProvider.allowedPrivateKeyWithoutCertificate) return Collections.enumeration(cache.keySet());
return new FilteredAliases(cache);
}
static void setKeyAlias(Key key, String alias) throws KeyStoreException
{
if (!(key instanceof UBPrivateKey) &&
!(key instanceof UBSecretKey)) throw new KeyStoreException("Key type is not supported");
((UBObject)key).partition.keyStore.engineSetKeyEntry(alias, key, null, null);
}
// -------------------- interface ------------------------
@Override
public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException
{
Entry entry;
try
{
if (password!=null && password.length!=0) partition.login(new String(password));
entry = findEntry(alias);
}
catch (CertificateException | InvalidKeySpecException | IOException e)
{
throw new ProviderException(e);
}
if (entry==null) return null;
if (entry.secretKey !=null) return entry.secretKey;
return entry.prvKey;
}
@Override
public Certificate[] engineGetCertificateChain(String alias)
{
Entry entry;
try { entry = findEntry(alias); }
catch (Exception e) { throw new ProviderException(e); }
if (entry==null) return null;
return entry.chain;
}
@Override
public Certificate engineGetCertificate(String alias)
{
Entry entry;
try { entry = findEntry(alias); }
catch (Exception e) { throw new ProviderException(e); }
if (entry==null) return null;
if (entry.cert==null) return null;
return entry.cert.x509;
}
@Override
public Date engineGetCreationDate(String alias)
{
Entry entry;
try { entry = findEntry(alias); }
catch (Exception e) { throw new ProviderException(e); }
if (entry==null) return null;
long initialDate = -1;
if (entry.secretKey !=null) initialDate = entry.secretKey.initialDate;
else if (entry.prvKey !=null) initialDate = entry.prvKey.initialDate;
else initialDate = entry.cert.initialDate;
if (initialDate<0) return null;
return new Date(initialDate * 1000);
}
@Override
public void engineSetEntry(String alias, java.security.KeyStore.Entry entry, java.security.KeyStore.ProtectionParameter protParam) throws KeyStoreException
{
char[] password = null;
if (protParam != null && protParam instanceof java.security.KeyStore.PasswordProtection) password = ((java.security.KeyStore.PasswordProtection)protParam).getPassword();
if (entry instanceof java.security.KeyStore.PrivateKeyEntry)
{
java.security.KeyStore.PrivateKeyEntry keyEntry = (java.security.KeyStore.PrivateKeyEntry)entry;
engineSetKeyEntry(alias, keyEntry.getPrivateKey(), password, keyEntry.getCertificateChain());
return;
}
if (entry instanceof java.security.KeyStore.SecretKeyEntry)
{
java.security.KeyStore.SecretKeyEntry secretKeyEntry = (java.security.KeyStore.SecretKeyEntry)entry;
engineSetKeyEntry(alias, secretKeyEntry.getSecretKey(), password, null);
return;
}
if (entry instanceof java.security.KeyStore.TrustedCertificateEntry)
{
java.security.KeyStore.TrustedCertificateEntry certEntry = (java.security.KeyStore.TrustedCertificateEntry)entry;
engineSetCertificateEntry(alias, certEntry.getTrustedCertificate());
return;
}
if (entry instanceof DYCryptoProvider.KeyEntry)
{
DYCryptoProvider.KeyEntry keyEntry = (DYCryptoProvider.KeyEntry)entry;
engineSetKeyEntry(alias, keyEntry.getPrivateKey(), password, null);
return;
}
throw new KeyStoreException(new UnsupportedOperationException("unsupported entry type: " + entry.getClass().getName()));
}
@Override
public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException
{
try
{
if (password!=null && password.length!=0) partition.login(new String(password));
UBSecretKey secretKey = (key instanceof UBSecretKey) ? (UBSecretKey)key : null;
UBPrivateKey privateKey = (key instanceof UBPrivateKey) ? (UBPrivateKey)key : null;
Entry entry = findEntry(alias);
if (entry!=null)
{
if (entry.isTrustedCert()) throw new KeyStoreException("Trusted certificate entry present");
if (privateKey==null && secretKey==null) engineDeleteEntry(alias);
}
if (chain!=null)
{
if (privateKey==null) privateKey = UBPrivateKey.newPrivateKey(null, partition, alias, key);
else privateKey.setName(alias);
X509Certificate x509 = (X509Certificate)chain[0];
UBCertificate cert = UBCertificate.locate(partition, x509);
if (cert==null) cert = new UBCertificate(partition, alias, x509);
else cert.setName(alias);
for (int i=1; i engineAliases()
{
synchronized (this)
{
long now = clock.millis();
if (now < lastCacheClock + CACHE_TIMEOUT) return getAliases();
}
try
{
long[] rsaIds = partition.locate(KMIP.ObjectType.PrivateKey, KMIP.CryptographicAlgorithm.RSA);
long[] eccIds = partition.locate(KMIP.ObjectType.PrivateKey, KMIP.CryptographicAlgorithm.EC);
long[] prvKeyIds = new long[rsaIds.length + eccIds.length];
System.arraycopy(rsaIds, 0, prvKeyIds, 0, rsaIds.length);
System.arraycopy(eccIds, 0, prvKeyIds, rsaIds.length, eccIds.length);
long[] certIds = partition.locate(KMIP.ObjectType.Certificate, 0);
UBObject[] prvKeys = UBObject.read(partition, prvKeyIds, true);
UBObject[] certs = UBObject.read(partition, certIds, true);
Map cache = new HashMap<>();
for (UBObject object : prvKeys)
{
UBPrivateKey key = (UBPrivateKey)object;
UBCertificate found = null;
for (int i=0; i