package gnu.crypto.jce.keyring; // -*- c-basic-offset: 3 -*- // --------------------------------------------------------------------------- // $Id: GnuKeyring.java,v 1.6 2005/10/06 04:24:15 rsdio Exp $ // // Copyright (C) 2003 Free Software Foundation, Inc. // // This file is part of GNU Crypto. // // GNU Crypto is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2, or (at your option) // any later version. // // GNU Crypto is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to the // // Free Software Foundation Inc., // 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301 // USA // // Linking this library statically or dynamically with other modules is // making a combined work based on this library. Thus, the terms and // conditions of the GNU General Public License cover the whole // combination. // // As a special exception, the copyright holders of this library give // you permission to link this library with independent modules to // produce an executable, regardless of the license terms of these // independent modules, and to copy and distribute the resulting // executable under terms of your choice, provided that you also meet, // for each linked independent module, the terms and conditions of the // license of that module. An independent module is a module which is // not derived from or based on this library. If you modify this // library, you may extend this exception to your version of the // library, but you are not obligated to do so. If you do not wish to // do so, delete this exception statement from your version. // // --------------------------------------------------------------------------- import java.io.BufferedInputStream; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; import java.security.Key; import java.security.KeyStoreSpi; import java.security.KeyStoreException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.util.Arrays; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import javax.crypto.SecretKey; import gnu.crypto.Registry; import gnu.crypto.keyring.IKeyring; import gnu.crypto.keyring.IPrivateKeyring; import gnu.crypto.keyring.IPublicKeyring; import gnu.crypto.keyring.GnuPrivateKeyring; import gnu.crypto.keyring.GnuPublicKeyring; import gnu.crypto.keyring.MalformedKeyringException; import gnu.crypto.keyring.PrimitiveEntry; public class GnuKeyring extends KeyStoreSpi { // Constants and fields. // ------------------------------------------------------------------------ private static final IllegalStateException NOT_LOADED = new IllegalStateException("keyring not loaded"); private boolean loaded; private IKeyring keyring; // Constructor. // ------------------------------------------------------------------------ public GnuKeyring() { } // Instance methods. // ------------------------------------------------------------------------ public Enumeration engineAliases() { if (!loaded) { throw NOT_LOADED; } if (keyring == null) { return new Enumeration() { public boolean hasMoreElements() { return false; } public Object nextElement() { throw new NoSuchElementException(); } }; } return keyring.aliases(); } public boolean engineContainsAlias(String alias) { if (!loaded) { throw NOT_LOADED; } if (keyring == null) { return false; } return keyring.containsAlias(alias); } public void engineDeleteEntry(String alias) { if (!loaded) { throw NOT_LOADED; } if (keyring != null) { keyring.remove(alias); } } public Certificate engineGetCertificate(String alias) { if (!loaded) { throw NOT_LOADED; } if (keyring == null) { return null; } if (!(keyring instanceof IPublicKeyring)) { throw new IllegalStateException("not a public keyring"); } return ((IPublicKeyring) keyring).getCertificate(alias); } public String engineGetCertificateAlias(Certificate cert) { if (!loaded) { throw NOT_LOADED; } if (keyring == null) { return null; } if (!(keyring instanceof IPublicKeyring)) { throw new IllegalStateException("not a public keyring"); } Enumeration aliases = keyring.aliases(); while (aliases.hasMoreElements()) { String alias = (String) aliases.nextElement(); Certificate cert2 = ((IPublicKeyring) keyring).getCertificate(alias); if (cert.equals(cert2)) { return alias; } } return null; } public void engineSetCertificateEntry(String alias, Certificate cert) { if (!loaded) { throw NOT_LOADED; } if (keyring == null) { keyring = new GnuPublicKeyring("HMAC-SHA-1", 20); } if (!(keyring instanceof IPublicKeyring)) { throw new IllegalStateException("not a public keyring"); } ((IPublicKeyring) keyring).putCertificate(alias, cert); } public Certificate[] engineGetCertificateChain(String alias) { if (!loaded) { throw NOT_LOADED; } if (keyring == null) { return null; } if (!(keyring instanceof IPrivateKeyring)) { throw new IllegalStateException("not a private keyring"); } return ((IPrivateKeyring) keyring).getCertPath(alias); } public Date engineGetCreationDate(String alias) { if (!loaded) { throw NOT_LOADED; } if (keyring == null) { return null; } List entries = keyring.get(alias); if (entries.size() == 0) { return null; } for (Iterator it = entries.iterator(); it.hasNext(); ) { Object o = it.next(); if (o instanceof PrimitiveEntry) { return ((PrimitiveEntry) o).getCreationDate(); } } return null; } public Key engineGetKey(String alias, char[] password) throws UnrecoverableKeyException { if (!loaded) { throw NOT_LOADED; } if (keyring == null) { return null; } if (!(keyring instanceof IPrivateKeyring)) { throw new IllegalStateException("not a private keyring"); } if (password == null) { if (((IPrivateKeyring) keyring).containsPublicKey(alias)) { return ((IPrivateKeyring) keyring).getPublicKey(alias); } } if (((IPrivateKeyring) keyring).containsPrivateKey(alias)) { return ((IPrivateKeyring) keyring).getPrivateKey(alias, password); } return null; } public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException { if (!loaded) { throw NOT_LOADED; } if (keyring == null) { keyring = new GnuPrivateKeyring("HMAC-SHA-1", 20, "AES", "OFB", 16); } if (!(keyring instanceof IPrivateKeyring)) { throw new IllegalStateException("not a private keyring"); } if (key instanceof PublicKey) { ((IPrivateKeyring) keyring).putPublicKey(alias, (PublicKey) key); return; } if (!(key instanceof PrivateKey) && !(key instanceof SecretKey)) { throw new KeyStoreException("cannot store keys of type " + key.getClass().getName()); } try { CertificateFactory fact = CertificateFactory.getInstance("X.509"); ((IPrivateKeyring) keyring).putCertPath(alias, chain); } catch (CertificateException ce) { throw new KeyStoreException(ce.toString()); } ((IPrivateKeyring) keyring).putPrivateKey(alias, key, password); } public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException { throw new KeyStoreException("method not supported"); } public boolean engineIsCertificateEntry(String alias) { if (!loaded) { throw NOT_LOADED; } if (keyring == null) { return false; } if (!(keyring instanceof IPublicKeyring)) { return false; } return ((IPublicKeyring) keyring).containsCertificate(alias); } public boolean engineIsKeyEntry(String alias) { if (!loaded) { throw NOT_LOADED; } if (keyring == null) { return false; } if (!(keyring instanceof IPrivateKeyring)) { return false; } return ((IPrivateKeyring) keyring).containsPublicKey(alias) || ((IPrivateKeyring) keyring).containsPrivateKey(alias); } public void engineLoad(InputStream in, char[] password) throws IOException { if (in != null) { if (!in.markSupported()) { in = new BufferedInputStream(in); } in.mark(5); for (int i = 0; i < 4; i++) if (in.read() != Registry.GKR_MAGIC[i]) throw new MalformedKeyringException("incorrect magic"); int usage = in.read(); in.reset(); HashMap attr = new HashMap(); attr.put(IKeyring.KEYRING_DATA_IN, in); attr.put(IKeyring.KEYRING_PASSWORD, password); switch (usage) { case GnuPublicKeyring.USAGE: keyring = new GnuPublicKeyring(); break; case GnuPrivateKeyring.USAGE: keyring = new GnuPrivateKeyring(); break; default: throw new MalformedKeyringException("unsupported ring usage: " + Integer.toBinaryString (usage)); } keyring.load(attr); } loaded = true; } public void engineStore(OutputStream out, char[] password) throws IOException { if (!loaded || keyring == null) { throw NOT_LOADED; } HashMap attr = new HashMap(); attr.put(IKeyring.KEYRING_DATA_OUT, out); attr.put(IKeyring.KEYRING_PASSWORD, password); keyring.store(attr); } public int engineSize() { if (!loaded) { throw NOT_LOADED; } if (keyring == null) { return 0; } return keyring.size(); } }