前言
本文使用语言为Kotlin,读者若有Java基础的也能看得懂 或者点击此处去学习下Kotlin
需求
需求是这样的,现在需要为客户建立一个KeyStore
不依靠openssl等命令行,使用代码进行对Keystore的增删改查
理解KeyStore相关API
文档是JDK11SE文档的一部分(需要有一定英文阅读能力)
参考官方在线文档或CSDN下载文档pdf
图说代码(新建)
先对KeyStore有个总体印象,可以作为拓展自行去了解,
本文专注于API实战,不过多介绍,能提供的相关资料会留在结尾
如图KeyStore管理了三类Key:单秘钥、秘钥对(私钥+证书)、单证书
Type 类型 常见PKCS12 JKS
provider 提供者 可为空
File 完整文件名
Parameter 用于保护KeyStore诸如访问密码、保护算法
# java.security.KeyStore.Builder 的构建方法 用于创建一个全新的KeyStore
public static Builder newInstance(String type, Provider provider, ProtectionParameter protection)
#实现了在桌面新建一个文件名newStore.p12 使用 PKCS12标准的 秘钥库
const val PATH = "C:\\Users\\Administrator\\Desktop\\newStore.p12"
const val PASSWORD = "123456"
fun main(){
val keyStore = KeyStore.Builder.newInstance("PKCS12",null,
KeyStore.PasswordProtection(null)).keyStore
keyStore.store(File(PATH).outputStream(),
PASSWORD.toCharArray())
}
用KeyStore Explorer打开输入密码后,看到一个空的KeyStore就创建好了
删改查篇
读取
导入前需要对上文创建的KeyStore进行读取
课本翻到 Key Management
public final void load(InputStream stream, char[] password)
throws IOException, NoSuchAlgorithmException, CertificateException
导入证书
本文不赘述证书相关API,可以去查看我其他文章(如果有) 补习入口
public final void setCertificateEntry(String alias, Certificate cert)
throws KeyStoreException
#对文件的读取、加入一份证书保存
const val PATH = "C:\\Users\\Administrator\\Desktop\\newStore.p12"
const val PASSWORD = "123456"
fun main(){
val keyStore = KeyStore.getInstance("PKCS12").apply {
load(File(PATH).inputStream(),PASSWORD.toCharArray())
}
keyStore.setCertificateEntry("client",getCert())//证书生成此处不说明
keyStore.store(File(PATH).outputStream(),PASSWORD.toCharArray())
}
导入单秘钥
知识补充:上图说明了各个Entry的对应关系
看到那个小锁了吗?没错!还能为秘钥设密码。
#放入Entry就看这个方法了
public final void setEntry(String alias, Entry entry,
ProtectionParameter protParam)
#当然,PasswordProtection 就对应了密码保护 可以于Entry一起放入KeyStore
public static class Passwo·rdProtection implements
ProtectionParameter
# 为之前的KeyStore加入一条私钥并设置与KeyStore相同的密码
fun main(){
val keyStore = KeyStore.getInstance("PKCS12").apply {
load(File(PATH).inputStream(),PASSWORD.toCharArray())
}
val key = KeyGenerator.getInstance("AES").apply {
init(256,SecureRandom("VARIABLE".toByteArray()))
}.generateKey()
keyStore.setEntry("symmetry",
KeyStore.SecretKeyEntry(key),
KeyStore.PasswordProtection(PASSWORD.toCharArray()))
keyStore.store(File(PATH).outputStream(),PASSWORD.toCharArray())
}
未解锁前信息都是不可见的
导入秘钥对
public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain)
#源码中对证书链有说明 数组的0号元素必须和私钥对应 即0号元素应该是Leaf Certificate
fun main(){
val keyStore = KeyStore.getInstance("PKCS12").apply {
load(File(PATH).inputStream(),PASSWORD.toCharArray())
}
val pair = genKeyPair()
keyStore.setEntry("privateKey",
KeyStore.PrivateKeyEntry(pair.private, certChain),
KeyStore.PasswordProtection(PASSWORD.toCharArray()))
//等效keystore.setKeyEntry("privateKey",pair.private, PASSWORD.toCharArray(),chain)
keyStore.store(File(PATH).outputStream(),PASSWORD.toCharArray())
}
引路
源码java.security.KeyStore
非对称加密 https://en.wikipedia.org/wiki/Symmetric-key_algorithm