FileDocCategorySizeDatePackage
JDKKeyStore.javaAPI DocAndroid 1.5 API30837Wed May 06 22:41:06 BST 2009org.bouncycastle.jce.provider

JDKKeyStore

public class JDKKeyStore extends KeyStoreSpi implements org.bouncycastle.jce.interfaces.BCKeyStore

Fields Summary
private static final int
STORE_VERSION
private static final int
STORE_SALT_SIZE
private static final String
STORE_CIPHER
private static final int
KEY_SALT_SIZE
private static final int
MIN_ITERATIONS
private static final String
KEY_CIPHER
static final int
NULL
static final int
CERTIFICATE
static final int
KEY
static final int
SECRET
static final int
SEALED
static final int
KEY_PRIVATE
static final int
KEY_PUBLIC
static final int
KEY_SECRET
protected Hashtable
table
protected SecureRandom
random
Constructors Summary
public JDKKeyStore()


     
    
    
Methods Summary
private java.security.cert.CertificatedecodeCertificate(java.io.DataInputStream dIn)

        String      type = dIn.readUTF();
        byte[]      cEnc = new byte[dIn.readInt()];

        dIn.readFully(cEnc);

        try
        {
            CertificateFactory cFact = CertificateFactory.getInstance(type, "BC");
            ByteArrayInputStream bIn = new ByteArrayInputStream(cEnc);

            return cFact.generateCertificate(bIn);
        }
        catch (NoSuchProviderException ex)
        {
            throw new IOException(ex.toString());
        }
        catch (CertificateException ex)
        {
            throw new IOException(ex.toString());
        }
    
private java.security.KeydecodeKey(java.io.DataInputStream dIn)

        int         keyType = dIn.read();
        String      format = dIn.readUTF();
        String      algorithm = dIn.readUTF();
        byte[]      enc = new byte[dIn.readInt()];
        KeySpec     spec;

        dIn.readFully(enc);

        if (format.equals("PKCS#8") || format.equals("PKCS8"))
        {
            spec = new PKCS8EncodedKeySpec(enc);
        }
        else if (format.equals("X.509") || format.equals("X509"))
        {
            spec = new X509EncodedKeySpec(enc);
        }
        else if (format.equals("RAW"))
        {
            return new SecretKeySpec(enc, algorithm);
        }
        else
        {
            throw new IOException("Key format " + format + " not recognised!");
        }

        try
        {
            switch (keyType)
            {
            case KEY_PRIVATE:
                return KeyFactory.getInstance(algorithm, "BC").generatePrivate(spec);
            case KEY_PUBLIC:
                return KeyFactory.getInstance(algorithm, "BC").generatePublic(spec);
            case KEY_SECRET:
                return SecretKeyFactory.getInstance(algorithm, "BC").generateSecret(spec);
            default:
                throw new IOException("Key type " + keyType + " not recognised!");
            }
        }
        catch (Exception e)
        {
            throw new IOException("Exception creating key: " + e.toString());
        }
    
private voidencodeCertificate(java.security.cert.Certificate cert, java.io.DataOutputStream dOut)

        try
        {
            byte[]      cEnc = cert.getEncoded();

            dOut.writeUTF(cert.getType());
            dOut.writeInt(cEnc.length);
            dOut.write(cEnc);
        }
        catch (CertificateEncodingException ex)
        {
            throw new IOException(ex.toString());
        }
    
private voidencodeKey(java.security.Key key, java.io.DataOutputStream dOut)

        byte[]      enc = key.getEncoded();

        if (key instanceof PrivateKey)
        {
            dOut.write(KEY_PRIVATE);
        }
        else if (key instanceof PublicKey)
        {
            dOut.write(KEY_PUBLIC);
        }
        else
        {
            dOut.write(KEY_SECRET);
        }
    
        dOut.writeUTF(key.getFormat());
        dOut.writeUTF(key.getAlgorithm());
        dOut.writeInt(enc.length);
        dOut.write(enc);
    
public java.util.EnumerationengineAliases()

        return table.keys();
    
public booleanengineContainsAlias(java.lang.String alias)

        return (table.get(alias) != null);
    
public voidengineDeleteEntry(java.lang.String alias)

        Object  entry = table.get(alias);

        if (entry == null)
        {
            throw new KeyStoreException("no such entry as " + alias);
        }

        table.remove(alias);
    
public java.security.cert.CertificateengineGetCertificate(java.lang.String alias)

        StoreEntry  entry = (StoreEntry)table.get(alias);

        if (entry != null)
        {
            if (entry.getType() == CERTIFICATE)
            {
                return (Certificate)entry.getObject();
            }
            else
            {
                Certificate[]   chain = entry.getCertificateChain();

                if (chain != null)
                {
                    return chain[0];
                }
            }
        }

        return null;
    
public java.lang.StringengineGetCertificateAlias(java.security.cert.Certificate cert)

        Enumeration e = table.elements();
        while (e.hasMoreElements())
        {
            StoreEntry  entry = (StoreEntry)e.nextElement();

            if (entry.getObject() instanceof Certificate)
            {
                Certificate c = (Certificate)entry.getObject();

                if (c.equals(cert))
                {
                    return entry.getAlias();
                }
            }
            else
            {
                Certificate[]   chain = entry.getCertificateChain();

                if (chain != null && chain[0].equals(cert))
                {
                    return entry.getAlias();
                }
            }
        }

        return null;
    
public java.security.cert.Certificate[]engineGetCertificateChain(java.lang.String alias)

        StoreEntry  entry = (StoreEntry)table.get(alias);

        if (entry != null)
        {
            return entry.getCertificateChain();
        }

        return null;
    
public java.util.DateengineGetCreationDate(java.lang.String alias)

        StoreEntry  entry = (StoreEntry)table.get(alias);

        if (entry != null)
        {
            return entry.getDate();
        }

        return null;
    
public java.security.KeyengineGetKey(java.lang.String alias, char[] password)

        StoreEntry  entry = (StoreEntry)table.get(alias);

        if (entry == null || entry.getType() == CERTIFICATE)
        {
            return null;
        }

        return (Key)entry.getObject(password);
    
public booleanengineIsCertificateEntry(java.lang.String alias)

        StoreEntry  entry = (StoreEntry)table.get(alias);

        if (entry != null && entry.getType() == CERTIFICATE)
        {
            return true;
        }
    
        return false;
    
public booleanengineIsKeyEntry(java.lang.String alias)

        StoreEntry  entry = (StoreEntry)table.get(alias);

        if (entry != null && entry.getType() != CERTIFICATE)
        {
            return true;
        }
    
        return false;
    
public voidengineLoad(java.io.InputStream stream, char[] password)

        table.clear();

        if (stream == null)     // just initialising
        {
            return;
        }

        DataInputStream     dIn = new DataInputStream(stream);
        int                 version = dIn.readInt();

        if (version != STORE_VERSION)
        {
            if (version != 0)
            {
                throw new IOException("Wrong version of key store.");
            }
        }

        byte[]      salt = new byte[dIn.readInt()];

        dIn.readFully(salt);

        int         iterationCount = dIn.readInt();

// BEGIN android-removed
//         HMac                    hMac = new HMac(new SHA1Digest());
//         MacInputStream          mIn = new MacInputStream(dIn, hMac);
//         PBEParametersGenerator  pbeGen = new PKCS12ParametersGenerator(new SHA1Digest());
// END android-removed
// BEGIN android-added
        HMac                    hMac = new HMac(OpenSSLMessageDigest.getInstance("SHA-1"));        
        MacInputStream          mIn = new MacInputStream(dIn, hMac);
        PBEParametersGenerator  pbeGen = new PKCS12ParametersGenerator(OpenSSLMessageDigest.getInstance("SHA-1"));
// END android-added
        byte[]                  passKey = PBEParametersGenerator.PKCS12PasswordToBytes(password);

        pbeGen.init(passKey, salt, iterationCount);

        hMac.init(pbeGen.generateDerivedMacParameters(hMac.getMacSize()));

        for (int i = 0; i != passKey.length; i++)
        {
            passKey[i] = 0;
        }

        loadStore(mIn);

        byte[]  mac = new byte[hMac.getMacSize()];
        byte[]  oldMac = new byte[hMac.getMacSize()];

        hMac.doFinal(mac, 0);

        for (int i = 0; i != oldMac.length; i++)
        {
            oldMac[i] = (byte)dIn.read();
        }

        //
        // we only do an integrity check if the password is provided.
        //
        if ((password != null && password.length != 0) && !isSameAs(mac, oldMac))
        {
            table.clear();
            throw new IOException("KeyStore integrity check failed.");
        }
    
public voidengineSetCertificateEntry(java.lang.String alias, java.security.cert.Certificate cert)

        StoreEntry  entry = (StoreEntry)table.get(alias);

        if (entry != null && entry.getType() != CERTIFICATE)
        {
            throw new KeyStoreException("key store already has an entry with alias " + alias);
        }

        table.put(alias, new StoreEntry(alias, cert));
    
public voidengineSetKeyEntry(java.lang.String alias, byte[] key, java.security.cert.Certificate[] chain)

        StoreEntry  entry = (StoreEntry)table.get(alias);

        if (entry != null)
        {
            throw new KeyStoreException("key store already has an entry with alias " + alias);
        }

        table.put(alias, new StoreEntry(alias, key, chain));
    
public voidengineSetKeyEntry(java.lang.String alias, java.security.Key key, char[] password, java.security.cert.Certificate[] chain)

        if ((key instanceof PrivateKey) && (chain == null))
        {
            throw new KeyStoreException("no certificate chain for private key");
        }

        StoreEntry  entry = (StoreEntry)table.get(alias);

        if (entry != null && entry.getType() == CERTIFICATE)
        {
            throw new KeyStoreException("key store already has an entry with alias " + alias);
        }

        try
        {
            table.put(alias, new StoreEntry(alias, key, password, chain));
        }
        catch (Exception e)
        {
            throw new KeyStoreException(e.toString());
        }
    
public intengineSize()

        return table.size();
    
public voidengineStore(java.io.OutputStream stream, char[] password)

        DataOutputStream    dOut = new DataOutputStream(stream);
        byte[]              salt = new byte[STORE_SALT_SIZE];
        int                 iterationCount = MIN_ITERATIONS + (random.nextInt() & 0x3ff);

        random.nextBytes(salt);

        dOut.writeInt(STORE_VERSION);
        dOut.writeInt(salt.length);
        dOut.write(salt);
        dOut.writeInt(iterationCount);

// BEGIN android-removed
//        HMac                    hMac = new HMac(new SHA1Digest());
//        MacOutputStream         mOut = new MacOutputStream(dOut, hMac);
//        PBEParametersGenerator  pbeGen = new PKCS12ParametersGenerator(new SHA1Digest());
// END android-removed
// BEGIN android-added
        HMac                    hMac = new HMac(OpenSSLMessageDigest.getInstance("SHA-1"));
        MacOutputStream         mOut = new MacOutputStream(dOut, hMac);
        PBEParametersGenerator  pbeGen = new PKCS12ParametersGenerator(OpenSSLMessageDigest.getInstance("SHA-1"));
// END android-added
        byte[]                  passKey = PBEParametersGenerator.PKCS12PasswordToBytes(password);

        pbeGen.init(passKey, salt, iterationCount);

        hMac.init(pbeGen.generateDerivedMacParameters(hMac.getMacSize()));

        for (int i = 0; i != passKey.length; i++)
        {
            passKey[i] = 0;
        }

        saveStore(mOut);

        byte[]  mac = new byte[hMac.getMacSize()];

        hMac.doFinal(mac, 0);

        dOut.write(mac);

        dOut.close();
    
protected booleanisSameAs(byte[] one, byte[] two)

        if (one.length != two.length)
        {
            return false;
        }

        for (int i = 0; i != one.length; i++)
        {
            if (one[i] != two[i])
            {
                return false;
            }
        }

        return true;
    
protected voidloadStore(java.io.InputStream in)

        DataInputStream     dIn = new DataInputStream(in);
        int                 type = dIn.read();

        while (type > NULL)
        {
            String          alias = dIn.readUTF();
            Date            date = new Date(dIn.readLong());
            int             chainLength = dIn.readInt();
            Certificate[]   chain = null;

            if (chainLength != 0)
            {
                chain = new Certificate[chainLength];

                for (int i = 0; i != chainLength; i++)
                {
                    chain[i] = decodeCertificate(dIn);
                }
            }

            switch (type)
            {
            case CERTIFICATE:
                    Certificate     cert = decodeCertificate(dIn);

                    table.put(alias, new StoreEntry(alias, date, CERTIFICATE, cert));
                    break;
            case KEY:
                    Key     key = decodeKey(dIn);
                    table.put(alias, new StoreEntry(alias, date, KEY, key, chain));
                    break;
            case SECRET:
            case SEALED:
                    byte[]      b = new byte[dIn.readInt()];

                    dIn.readFully(b);
                    table.put(alias, new StoreEntry(alias, date, type, b, chain));
                    break;
            default:
                    throw new RuntimeException("Unknown object type in store.");
            }

            type = dIn.read();
        }
    
protected javax.crypto.CiphermakePBECipher(java.lang.String algorithm, int mode, char[] password, byte[] salt, int iterationCount)

        try
        {
            PBEKeySpec          pbeSpec = new PBEKeySpec(password);
            SecretKeyFactory    keyFact = SecretKeyFactory.getInstance(algorithm, "BC");
            PBEParameterSpec    defParams = new PBEParameterSpec(salt, iterationCount);

            Cipher cipher = Cipher.getInstance(algorithm, "BC");

            cipher.init(mode, keyFact.generateSecret(pbeSpec), defParams);

            return cipher;
        }
        catch (Exception e)
        {
            throw new IOException("Error initialising store of key store: " + e);
        }
    
protected voidsaveStore(java.io.OutputStream out)

        Enumeration         e = table.elements();
        DataOutputStream    dOut = new DataOutputStream(out);

        while (e.hasMoreElements())
        {
            StoreEntry  entry = (StoreEntry)e.nextElement();

            dOut.write(entry.getType());
            dOut.writeUTF(entry.getAlias());
            dOut.writeLong(entry.getDate().getTime());

            Certificate[]   chain = entry.getCertificateChain();
            if (chain == null)
            {
                dOut.writeInt(0);
            }
            else
            {
                dOut.writeInt(chain.length);
                for (int i = 0; i != chain.length; i++)
                {
                    encodeCertificate(chain[i], dOut);
                }
            }

            switch (entry.getType())
            {
            case CERTIFICATE:
                    encodeCertificate((Certificate)entry.getObject(), dOut);
                    break;
            case KEY:
                    encodeKey((Key)entry.getObject(), dOut);
                    break;
            case SEALED:
            case SECRET:
                    byte[]  b = (byte[])entry.getObject();

                    dOut.writeInt(b.length);
                    dOut.write(b);
                    break;
            default:
                    throw new RuntimeException("Unknown object type in store.");
            }
        }

        dOut.write(NULL);
    
public voidsetRandom(java.security.SecureRandom rand)

        this.random = rand;