diff options
Diffstat (limited to 'libraries/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi.java')
-rw-r--r-- | libraries/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi.java | 1061 |
1 files changed, 0 insertions, 1061 deletions
diff --git a/libraries/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi.java b/libraries/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi.java deleted file mode 100644 index a06ae3917..000000000 --- a/libraries/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi.java +++ /dev/null @@ -1,1061 +0,0 @@ -package org.spongycastle.jcajce.provider.keystore.bc; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.Key; -import java.security.KeyFactory; -import java.security.KeyStoreException; -import java.security.KeyStoreSpi; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.SecureRandom; -import java.security.UnrecoverableKeyException; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.spec.KeySpec; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; -import java.util.Date; -import java.util.Enumeration; -import java.util.Hashtable; - -import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; -import javax.crypto.CipherOutputStream; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import javax.crypto.spec.PBEParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -import org.spongycastle.crypto.CipherParameters; -import org.spongycastle.crypto.Digest; -import org.spongycastle.crypto.PBEParametersGenerator; -import org.spongycastle.crypto.digests.SHA1Digest; -import org.spongycastle.crypto.generators.PKCS12ParametersGenerator; -import org.spongycastle.crypto.io.DigestInputStream; -import org.spongycastle.crypto.io.DigestOutputStream; -import org.spongycastle.crypto.io.MacInputStream; -import org.spongycastle.crypto.io.MacOutputStream; -import org.spongycastle.crypto.macs.HMac; -import org.spongycastle.jce.interfaces.BCKeyStore; -import org.spongycastle.jce.provider.BouncyCastleProvider; -import org.spongycastle.util.Arrays; -import org.spongycastle.util.io.Streams; -import org.spongycastle.util.io.TeeOutputStream; - -public class BcKeyStoreSpi - extends KeyStoreSpi - implements BCKeyStore -{ - private static final int STORE_VERSION = 2; - - private static final int STORE_SALT_SIZE = 20; - private static final String STORE_CIPHER = "PBEWithSHAAndTwofish-CBC"; - - private static final int KEY_SALT_SIZE = 20; - private static final int MIN_ITERATIONS = 1024; - - private static final String KEY_CIPHER = "PBEWithSHAAnd3-KeyTripleDES-CBC"; - - // - // generic object types - // - static final int NULL = 0; - static final int CERTIFICATE = 1; - static final int KEY = 2; - static final int SECRET = 3; - static final int SEALED = 4; - - // - // key types - // - static final int KEY_PRIVATE = 0; - static final int KEY_PUBLIC = 1; - static final int KEY_SECRET = 2; - - protected Hashtable table = new Hashtable(); - - protected SecureRandom random = new SecureRandom(); - - protected int version; - - public BcKeyStoreSpi(int version) - { - this.version = version; - } - - private class StoreEntry - { - int type; - String alias; - Object obj; - Certificate[] certChain; - Date date = new Date(); - - StoreEntry( - String alias, - Certificate obj) - { - this.type = CERTIFICATE; - this.alias = alias; - this.obj = obj; - this.certChain = null; - } - - StoreEntry( - String alias, - byte[] obj, - Certificate[] certChain) - { - this.type = SECRET; - this.alias = alias; - this.obj = obj; - this.certChain = certChain; - } - - StoreEntry( - String alias, - Key key, - char[] password, - Certificate[] certChain) - throws Exception - { - this.type = SEALED; - this.alias = alias; - this.certChain = certChain; - - byte[] salt = new byte[KEY_SALT_SIZE]; - - random.setSeed(System.currentTimeMillis()); - random.nextBytes(salt); - - int iterationCount = MIN_ITERATIONS + (random.nextInt() & 0x3ff); - - - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - DataOutputStream dOut = new DataOutputStream(bOut); - - dOut.writeInt(salt.length); - dOut.write(salt); - dOut.writeInt(iterationCount); - - Cipher cipher = makePBECipher(KEY_CIPHER, Cipher.ENCRYPT_MODE, password, salt, iterationCount); - CipherOutputStream cOut = new CipherOutputStream(dOut, cipher); - - dOut = new DataOutputStream(cOut); - - encodeKey(key, dOut); - - dOut.close(); - - obj = bOut.toByteArray(); - } - - StoreEntry( - String alias, - Date date, - int type, - Object obj) - { - this.alias = alias; - this.date = date; - this.type = type; - this.obj = obj; - } - - StoreEntry( - String alias, - Date date, - int type, - Object obj, - Certificate[] certChain) - { - this.alias = alias; - this.date = date; - this.type = type; - this.obj = obj; - this.certChain = certChain; - } - - int getType() - { - return type; - } - - String getAlias() - { - return alias; - } - - Object getObject() - { - return obj; - } - - Object getObject( - char[] password) - throws NoSuchAlgorithmException, UnrecoverableKeyException - { - if (password == null || password.length == 0) - { - if (obj instanceof Key) - { - return obj; - } - } - - if (type == SEALED) - { - ByteArrayInputStream bIn = new ByteArrayInputStream((byte[])obj); - DataInputStream dIn = new DataInputStream(bIn); - - try - { - byte[] salt = new byte[dIn.readInt()]; - - dIn.readFully(salt); - - int iterationCount = dIn.readInt(); - - Cipher cipher = makePBECipher(KEY_CIPHER, Cipher.DECRYPT_MODE, password, salt, iterationCount); - - CipherInputStream cIn = new CipherInputStream(dIn, cipher); - - try - { - return decodeKey(new DataInputStream(cIn)); - } - catch (Exception x) - { - bIn = new ByteArrayInputStream((byte[])obj); - dIn = new DataInputStream(bIn); - - salt = new byte[dIn.readInt()]; - - dIn.readFully(salt); - - iterationCount = dIn.readInt(); - - cipher = makePBECipher("Broken" + KEY_CIPHER, Cipher.DECRYPT_MODE, password, salt, iterationCount); - - cIn = new CipherInputStream(dIn, cipher); - - Key k = null; - - try - { - k = decodeKey(new DataInputStream(cIn)); - } - catch (Exception y) - { - bIn = new ByteArrayInputStream((byte[])obj); - dIn = new DataInputStream(bIn); - - salt = new byte[dIn.readInt()]; - - dIn.readFully(salt); - - iterationCount = dIn.readInt(); - - cipher = makePBECipher("Old" + KEY_CIPHER, Cipher.DECRYPT_MODE, password, salt, iterationCount); - - cIn = new CipherInputStream(dIn, cipher); - - k = decodeKey(new DataInputStream(cIn)); - } - - // - // reencrypt key with correct cipher. - // - if (k != null) - { - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - DataOutputStream dOut = new DataOutputStream(bOut); - - dOut.writeInt(salt.length); - dOut.write(salt); - dOut.writeInt(iterationCount); - - Cipher out = makePBECipher(KEY_CIPHER, Cipher.ENCRYPT_MODE, password, salt, iterationCount); - CipherOutputStream cOut = new CipherOutputStream(dOut, out); - - dOut = new DataOutputStream(cOut); - - encodeKey(k, dOut); - - dOut.close(); - - obj = bOut.toByteArray(); - - return k; - } - else - { - throw new UnrecoverableKeyException("no match"); - } - } - } - catch (Exception e) - { - throw new UnrecoverableKeyException("no match"); - } - } - else - { - throw new RuntimeException("forget something!"); - // TODO - // if we get to here key was saved as byte data, which - // according to the docs means it must be a private key - // in EncryptedPrivateKeyInfo (PKCS8 format), later... - // - } - } - - Certificate[] getCertificateChain() - { - return certChain; - } - - Date getDate() - { - return date; - } - } - - private void encodeCertificate( - Certificate cert, - DataOutputStream dOut) - throws IOException - { - 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 Certificate decodeCertificate( - DataInputStream dIn) - throws IOException - { - String type = dIn.readUTF(); - byte[] cEnc = new byte[dIn.readInt()]; - - dIn.readFully(cEnc); - - try - { - CertificateFactory cFact = CertificateFactory.getInstance(type, BouncyCastleProvider.PROVIDER_NAME); - 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 void encodeKey( - Key key, - DataOutputStream dOut) - throws IOException - { - 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); - } - - private Key decodeKey( - DataInputStream dIn) - throws IOException - { - 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, BouncyCastleProvider.PROVIDER_NAME).generatePrivate(spec); - case KEY_PUBLIC: - return KeyFactory.getInstance(algorithm, BouncyCastleProvider.PROVIDER_NAME).generatePublic(spec); - case KEY_SECRET: - return SecretKeyFactory.getInstance(algorithm, BouncyCastleProvider.PROVIDER_NAME).generateSecret(spec); - default: - throw new IOException("Key type " + keyType + " not recognised!"); - } - } - catch (Exception e) - { - throw new IOException("Exception creating key: " + e.toString()); - } - } - - protected Cipher makePBECipher( - String algorithm, - int mode, - char[] password, - byte[] salt, - int iterationCount) - throws IOException - { - try - { - PBEKeySpec pbeSpec = new PBEKeySpec(password); - SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm, BouncyCastleProvider.PROVIDER_NAME); - PBEParameterSpec defParams = new PBEParameterSpec(salt, iterationCount); - - Cipher cipher = Cipher.getInstance(algorithm, BouncyCastleProvider.PROVIDER_NAME); - - cipher.init(mode, keyFact.generateSecret(pbeSpec), defParams); - - return cipher; - } - catch (Exception e) - { - throw new IOException("Error initialising store of key store: " + e); - } - } - - public void setRandom( - SecureRandom rand) - { - this.random = rand; - } - - public Enumeration engineAliases() - { - return table.keys(); - } - - public boolean engineContainsAlias( - String alias) - { - return (table.get(alias) != null); - } - - public void engineDeleteEntry( - String alias) - throws KeyStoreException - { - Object entry = table.get(alias); - - if (entry == null) - { - return; - } - - table.remove(alias); - } - - public Certificate engineGetCertificate( - 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 String engineGetCertificateAlias( - 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 Certificate[] engineGetCertificateChain( - String alias) - { - StoreEntry entry = (StoreEntry)table.get(alias); - - if (entry != null) - { - return entry.getCertificateChain(); - } - - return null; - } - - public Date engineGetCreationDate(String alias) - { - StoreEntry entry = (StoreEntry)table.get(alias); - - if (entry != null) - { - return entry.getDate(); - } - - return null; - } - - public Key engineGetKey( - String alias, - char[] password) - throws NoSuchAlgorithmException, UnrecoverableKeyException - { - StoreEntry entry = (StoreEntry)table.get(alias); - - if (entry == null || entry.getType() == CERTIFICATE) - { - return null; - } - - return (Key)entry.getObject(password); - } - - public boolean engineIsCertificateEntry( - String alias) - { - StoreEntry entry = (StoreEntry)table.get(alias); - - if (entry != null && entry.getType() == CERTIFICATE) - { - return true; - } - - return false; - } - - public boolean engineIsKeyEntry( - String alias) - { - StoreEntry entry = (StoreEntry)table.get(alias); - - if (entry != null && entry.getType() != CERTIFICATE) - { - return true; - } - - return false; - } - - public void engineSetCertificateEntry( - String alias, - Certificate cert) - throws KeyStoreException - { - StoreEntry entry = (StoreEntry)table.get(alias); - - if (entry != null && entry.getType() != CERTIFICATE) - { - throw new KeyStoreException("key store already has a key entry with alias " + alias); - } - - table.put(alias, new StoreEntry(alias, cert)); - } - - public void engineSetKeyEntry( - String alias, - byte[] key, - Certificate[] chain) - throws KeyStoreException - { - table.put(alias, new StoreEntry(alias, key, chain)); - } - - public void engineSetKeyEntry( - String alias, - Key key, - char[] password, - Certificate[] chain) - throws KeyStoreException - { - if ((key instanceof PrivateKey) && (chain == null)) - { - throw new KeyStoreException("no certificate chain for private key"); - } - - try - { - table.put(alias, new StoreEntry(alias, key, password, chain)); - } - catch (Exception e) - { - throw new KeyStoreException(e.toString()); - } - } - - public int engineSize() - { - return table.size(); - } - - protected void loadStore( - InputStream in) - throws IOException - { - 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 void saveStore( - OutputStream out) - throws IOException - { - 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 void engineLoad( - InputStream stream, - char[] password) - throws IOException - { - table.clear(); - - if (stream == null) // just initialising - { - return; - } - - DataInputStream dIn = new DataInputStream(stream); - int version = dIn.readInt(); - - if (version != STORE_VERSION) - { - if (version != 0 && version != 1) - { - throw new IOException("Wrong version of key store."); - } - } - - int saltLength = dIn.readInt(); - if (saltLength <= 0) - { - throw new IOException("Invalid salt detected"); - } - - byte[] salt = new byte[saltLength]; - - dIn.readFully(salt); - - int iterationCount = dIn.readInt(); - - // - // we only do an integrity check if the password is provided. - // - HMac hMac = new HMac(new SHA1Digest()); - if (password != null && password.length != 0) - { - byte[] passKey = PBEParametersGenerator.PKCS12PasswordToBytes(password); - - PBEParametersGenerator pbeGen = new PKCS12ParametersGenerator(new SHA1Digest()); - pbeGen.init(passKey, salt, iterationCount); - - CipherParameters macParams; - - if (version != 2) - { - macParams = pbeGen.generateDerivedMacParameters(hMac.getMacSize()); - } - else - { - macParams = pbeGen.generateDerivedMacParameters(hMac.getMacSize() * 8); - } - - Arrays.fill(passKey, (byte)0); - - hMac.init(macParams); - MacInputStream mIn = new MacInputStream(dIn, hMac); - - loadStore(mIn); - - // Finalise our mac calculation - byte[] mac = new byte[hMac.getMacSize()]; - hMac.doFinal(mac, 0); - - // TODO Should this actually be reading the remainder of the stream? - // Read the original mac from the stream - byte[] oldMac = new byte[hMac.getMacSize()]; - dIn.readFully(oldMac); - - if (!Arrays.constantTimeAreEqual(mac, oldMac)) - { - table.clear(); - throw new IOException("KeyStore integrity check failed."); - } - } - else - { - loadStore(dIn); - - // TODO Should this actually be reading the remainder of the stream? - // Parse the original mac from the stream too - byte[] oldMac = new byte[hMac.getMacSize()]; - dIn.readFully(oldMac); - } - } - - - public void engineStore(OutputStream stream, char[] password) - throws IOException - { - DataOutputStream dOut = new DataOutputStream(stream); - byte[] salt = new byte[STORE_SALT_SIZE]; - int iterationCount = MIN_ITERATIONS + (random.nextInt() & 0x3ff); - - random.nextBytes(salt); - - dOut.writeInt(version); - dOut.writeInt(salt.length); - dOut.write(salt); - dOut.writeInt(iterationCount); - - HMac hMac = new HMac(new SHA1Digest()); - MacOutputStream mOut = new MacOutputStream(hMac); - PBEParametersGenerator pbeGen = new PKCS12ParametersGenerator(new SHA1Digest()); - byte[] passKey = PBEParametersGenerator.PKCS12PasswordToBytes(password); - - pbeGen.init(passKey, salt, iterationCount); - - if (version < 2) - { - hMac.init(pbeGen.generateDerivedMacParameters(hMac.getMacSize())); - } - else - { - hMac.init(pbeGen.generateDerivedMacParameters(hMac.getMacSize() * 8)); - } - - for (int i = 0; i != passKey.length; i++) - { - passKey[i] = 0; - } - - saveStore(new TeeOutputStream(dOut, mOut)); - - byte[] mac = new byte[hMac.getMacSize()]; - - hMac.doFinal(mac, 0); - - dOut.write(mac); - - dOut.close(); - } - - /** - * the BouncyCastle store. This wont work with the key tool as the - * store is stored encrypted on disk, so the password is mandatory, - * however if you hard drive is in a bad part of town and you absolutely, - * positively, don't want nobody peeking at your things, this is the - * one to use, no problem! After all in a Bouncy Castle nothing can - * touch you. - * - * Also referred to by the alias UBER. - */ - public static class BouncyCastleStore - extends BcKeyStoreSpi - { - public BouncyCastleStore() - { - super(1); - } - - public void engineLoad( - InputStream stream, - char[] password) - throws IOException - { - table.clear(); - - if (stream == null) // just initialising - { - return; - } - - DataInputStream dIn = new DataInputStream(stream); - int version = dIn.readInt(); - - if (version != STORE_VERSION) - { - if (version != 0 && version != 1) - { - throw new IOException("Wrong version of key store."); - } - } - - byte[] salt = new byte[dIn.readInt()]; - - if (salt.length != STORE_SALT_SIZE) - { - throw new IOException("Key store corrupted."); - } - - dIn.readFully(salt); - - int iterationCount = dIn.readInt(); - - if ((iterationCount < 0) || (iterationCount > 4 * MIN_ITERATIONS)) - { - throw new IOException("Key store corrupted."); - } - - String cipherAlg; - if (version == 0) - { - cipherAlg = "Old" + STORE_CIPHER; - } - else - { - cipherAlg = STORE_CIPHER; - } - - Cipher cipher = this.makePBECipher(cipherAlg, Cipher.DECRYPT_MODE, password, salt, iterationCount); - CipherInputStream cIn = new CipherInputStream(dIn, cipher); - - Digest dig = new SHA1Digest(); - DigestInputStream dgIn = new DigestInputStream(cIn, dig); - - this.loadStore(dgIn); - - // Finalise our digest calculation - byte[] hash = new byte[dig.getDigestSize()]; - dig.doFinal(hash, 0); - - // TODO Should this actually be reading the remainder of the stream? - // Read the original digest from the stream - byte[] oldHash = new byte[dig.getDigestSize()]; - Streams.readFully(cIn, oldHash); - - if (!Arrays.constantTimeAreEqual(hash, oldHash)) - { - table.clear(); - throw new IOException("KeyStore integrity check failed."); - } - } - - public void engineStore(OutputStream stream, char[] password) - throws IOException - { - Cipher cipher; - DataOutputStream dOut = new DataOutputStream(stream); - byte[] salt = new byte[STORE_SALT_SIZE]; - int iterationCount = MIN_ITERATIONS + (random.nextInt() & 0x3ff); - - random.nextBytes(salt); - - dOut.writeInt(version); - dOut.writeInt(salt.length); - dOut.write(salt); - dOut.writeInt(iterationCount); - - cipher = this.makePBECipher(STORE_CIPHER, Cipher.ENCRYPT_MODE, password, salt, iterationCount); - - CipherOutputStream cOut = new CipherOutputStream(dOut, cipher); - DigestOutputStream dgOut = new DigestOutputStream(new SHA1Digest()); - - this.saveStore(new TeeOutputStream(cOut, dgOut)); - - byte[] dig = dgOut.getDigest(); - - cOut.write(dig); - - cOut.close(); - } - } - - public static class Std - extends BcKeyStoreSpi - { - public Std() - { - super(STORE_VERSION); - } - } - - public static class Version1 - extends BcKeyStoreSpi - { - public Version1() - { - super(1); - } - } -} |