3.2.17 KeyStore
KeyStore类被称为密钥库,用于管理密钥和证书的存储。KeyStore类是个引擎类,它提供一些相当完善的接口来访问和修改密钥仓库中的信息。
//用于管理密钥和证书存储。
public class KeyStore
extends Object
❑方法详述
KeyStore类同样需要通过getInstance()工厂方法获得实例化对象。
我们可以通过指定密钥库类型获得实例化对象,方法如下所示:
//返回指定类型的KeyStore对象。
public static KeyStore getInstance(String type)
另一种方式就是指定密钥库类型时指定该密钥库类型的提供者,方法如下所示:
//返回指定类型的KeyStore对象。
public static KeyStore getInstance(String type, Provider provider)
//返回指定类型的KeyStore对象。
public static KeyStore getInstance(String type, String provider)
完成实例化操作后,我们将进行以下操作:
/返回Java安全属性文件中指定的默认密钥库类型;如果不存在此类属性,则返回字符串"jks"("Javakeystore"的首字母缩写)。/
public final static String getDefaultType()
密钥库类型不区分大小。例如,“JKS”被认为与“jks”相同。除了JKS这种类型以外,还有PKCS12和JCEKS两种类型。JCEKS本身受美国出口限制,所以通常我们可以使用的只有JKS和PKCS12两种类型。但PKCS12这种类型的密钥库管理支持不是很完备,只能够读取该类型的证书,却不能对其进行修改。因此,JKS是最好的选择。
与获取默认密钥库类型方法相对的是如下取得当前密钥库类型的方法:
//返回此密钥库的类型。
public final String getType()
通过以下两种方法来加载和存储密钥库:
//从给定输入流中加载此密钥库。
public final void load(InputStream stream, char[]password)
//将此密钥库存储到给定输出流,并用给定密码保护其完整性。
public final void store(OutputStream stream, char[]password)
通过以下方法获得密钥库中的条目数:
//获取此密钥库中的条目数。
public final int size()
我们依旧可以使用如下方法获得提供者:
//返回此密钥库的提供者。
public final Provider getProvider()
在密钥库中,密钥和证书都是通过别名进行组织的。
可通过以下方法获得密钥库的别名列表,以及确认给定的别名是否在当前密钥库中:
//列出此密钥库的所有别名。
public final Enumeration<String>aliases()//检查给定别名是否存在于此密钥库中。
public final boolean containsAlias(String alias)
我们可以通过别名和密码来获得密钥:
//返回与给定别名关联的密钥,并用给定密码来恢复它。
public final Key getKey(String alias, char[]password)
这里要注意一下,虽然返回的类型是Key接口,但真正获得的是PrivateKey接口的实例。
通过该方法将获得该别名在密钥库中对应的私钥。
通过别名,我们还可以获得证书或证书链:
//返回与给定别名关联的证书。
public final Certificate getCertificate(String alias)
//返回与给定别名关联的证书链。
public final Certificate[]getCertificateChain(String alias)
反之,通过证书获得其在密钥库中的别名:
//返回证书与给定证书匹配的第一个密钥库条目的别名。
public final String getCertificateAlias(Certificate cert)
同样,能通过别名获得其对应条码的创建日期:
//返回给定别名标识的条目的创建日期。
public final Date getCreationDate(String alias)
通过别名来删除密钥库中与别名相对应的条目:
//删除此密钥库中给定别名标识的条目。
public final void deleteEntry(String alias)
我们一直在说“条目”这个词,是因为在密钥库中别名可能对应密钥,有可能对应证书。我们通过以下方法设置别名与密钥和证书的对应关系。
//将给定密钥(受保护的)分配给指定的别名。
public final void setKeyEntry(String alias, byte[]key, Certificate[]chain)
//将给定的密钥分配给给定的别名,并用给定密码保护它。
public final void setKeyEntry(String alias, Key key, char[]password,
Certificate[]chain)
我们也可以使用如下方法将别名与证书绑定:
//将给定可信证书分配给给定别名。
public final void setCertificateEntry(String alias, Certificate cert)
既然,别名可能对应密钥或证书,那么需要方法来判别:
/如果给定别名标识的条目是通过调用setCertificateEntry或者以TrustedCertificateEntry为参数的setEntry创建的,则返回true。/
public final boolean isCertificateEntry(String alias)
/如果给定别名标识的条目是通过调用setKeyEntry或者以PrivateKeyEntry或SecretKeyEntry为参数的setEntry创建的,则返回true。/
public final boolean isKeyEntry(String alias)
在上述方法的注释中,我们注意到一些Java 5之前所没有的内容。在Java 5以后,KeyStore类中加入了新的内部接口及内部类。
KeyStore. Entry接口:
//用于密钥库项类型的标记接口。
public static interface KeyStore.Entry
KeyStore. Entry接口是一个空接口,内部没有定义代码,用于类型区分。
KeyStore管理不同类型的条目。每种类型的条目都实现KeyStore.Entry接口。提供了三种基本的KeyStore.Entry实现:
//保存私钥和相应证书链的密钥库项。
public static final class KeyStore.PrivateKeyEntry
//保存秘密密钥的密钥库项。
public static final class KeyStore.SecretKeyEntry
//保存可信的证书的密钥库项。
public static final class KeyStore.TrustedCertificateEntry
·KeyStore. PrivateKeyEntry
我们把KeyStore.PrivateKeyEntry称为私钥项。可通过以下方法获得实例化对象:
//构造带私钥和相应证书链的私钥项。
public KeyStore.PrivateKeyEntry(PrivateKey privateKey, Certificate[]chain)
获得私钥项对象后,就可以获得其相应的属性:
/从此私钥项内部的证书链数组首位中获取证书。如果证书的类型是X.509,返回证书的运行时类型是X509Certificate/
public Certificate getCertificate()
//从此私钥项获取证书链。
public Certificate[]getCertificateChain()
//从此私钥项获取PrivateKey对象。
public PrivateKey getPrivateKey()
此外,私钥项覆盖了如下方法:
//返回此私钥项的字符串表示形式。
public String toString()
·KeyStore. SecretKeyEntry
我们把KeyStore.SecretKeyEntry称为秘密密钥项。可通过以下方法获得实例化对象:
//用秘密密钥构造秘密密钥项。
public KeyStore.SecretKeyEntry(SecretKey secretKey)
秘密密钥项的主要作用就是保护秘密密钥,可通过如下方法获得秘密密钥:
//从此项中获取SecretKey对象。
public SecretKey getSecretKey()
此外,秘密密钥项覆盖了如下方法:
//返回此秘密密钥项的字符串表示形式。
public String toString()
·KeyStore. TrustedCertificateEntry
我们把KeyStore.TrustedCertificateEntry称为信任证书项,可通过以下方法获得实例化对象:
//用可信证书构造信任证书项。
public KeyStore.TrustedCertificateEntry(Certificate trustedCert)
与秘密密钥项相似,信任证书项主要保护受信任的证书,可通过如下方法获得其证书:
//从此信任证书项获取可信证书。
public Certificate getTrustedCertificate()
此外,秘密密钥项覆盖了如下方法:
//返回此信任证书项的字符串表示形式。
public String toString()
在理解了上述各种KeyStore.Entry的具体实现后,我们来了解一下密钥库中与KeyStore.Entry相关的方法:
//确定指定别名的密钥库项是否是指定密钥库项的实例或子类。
public final boolean entryInstanceOf(String alias, Class<?extends KeyStore.Entry>entryClass)
除了上述内部接口与内部实现外,还有其他内部接口及相应的内部实现。由于内容与本书所涉及的方面关联较少,故不在这里详述。有兴趣的读者朋友可以参考相关API文档。
❑实现示例
我们通过代码清单3-16来演示如何获得密钥库对象。
代码清单3-16 加载密钥库
//加载密钥库文件
FileInputStream is=new FileInputStream("D:\.keystore");
//实例化KeyStore对象
KeyStore ks=KeyStore.getInstance(KeyStore.getDefaultType());
//加载密钥库,使用密码"password"。
ks.load(is,"password".toCharArray());
//关闭文件流
is.close();
得到密钥库对象后,可以获得其别名对应的私钥:
//获得别名为"alias"所对应的私钥。
PrivateKey key=(PrivateKey)ks.getKey("alias","password".toCharArray());
或者使用以下私钥项的方式获得私钥:
//获得私钥项
KeyStore.PrivateKeyEntry pkEntry=(KeyStore.PrivateKeyEntry)ks.getEntry("alias",
"password".toCharArray());
//获得私钥
PrivateKey privateKey=pkEntry.getPrivateKey();
有关证书类Certificate请关注3.5.1节。