最近项目有一个需求,客户要求将密码保存在keyStore文件中。平时开发的WEB项目,密码明文都是加密后以密文的形式保存在数据库中,第一次遇到这种需求,网上查阅相关资料,大多都是基于android的代码,没有找到基于B/S架构的源码,无奈之下只好自己查阅API编写代码,现公布于众,希望大家交流指导!
一、需求
将项目中文件的解密密码保存于keystore文件中,使用时再从keystore文件中取出;
二、开发步骤
1、使用keytool工具生成keystore文件,命令如下:
keytool -genkey -alias csdn -keypass 123456 -keyalg RSA -keysize 1024 -validity 3650 -keystore D:/csdn_server.keystore -storepass 888999 -storetype jceks
keytool命令位于:...\Java\jdk1.7.0_80\bin文件夹中;
相关参数解释如下:
-alias 产生别名 ,别名中包含用户的公钥、私钥和证书
-keypass 指定别名条目的密码(私钥的密码)
-keyalg 指定密钥的算法 (如 RSA DSA(如果不指定默认采用DSA))
-keysize 指定密钥长度
-validity 指定创建的证书有效期多少天
-keystore 指定密钥库的名称(产生的各类信息将不在.keystore文件中)
-storepass 指定密钥库的密码(获取keystore信息所需的密码)
-storetype java默认的密钥库类型为JKS, 除这种类型外,还有PKCS12、JCEKS两种类型,要存储secret key要使用JCEKS类型,另外两种不支持。
2、保存密码于keystore文件中;
package test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.KeyStore.ProtectionParameter;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableEntryException;
import java.security.cert.CertificateException;
import javax.crypto.spec.SecretKeySpec;
public class KeystroreUtil {
public static void main(String[] args) {
FileInputStream fis = null;
OutputStream os = null;
try {
// 读取keystore文件转换为keystore密钥库对象
fis = new FileInputStream("D:/csdn_server.keystore");
// 生成证书的类型为jceks
KeyStore keyStore = KeyStore.getInstance("jceks");
// 该密钥库的密码"888999",storepass指定密钥库的密码(获取keystore信息所需的密码)
String storepass = "888999";
keyStore.load(fis, storepass.toCharArray());
fis.close();
// 一旦加载了 keystore,就能够从 keystore 读取现有条目,或向 keystore 写入新条目:
String alias = "csdn";// 别名
String keypass = "123456"; // 别名密码 ,keypass 指定别名条目的密码(私钥的密码)
ProtectionParameter param = new KeyStore.PasswordProtection(keypass.toCharArray());
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, param);
PrivateKey myPrivateKey = pkEntry.getPrivateKey();
System.out.println("获取的私钥是:" + myPrivateKey.toString());
// 根据给定的字节数组构造一个密钥
String desPwd = "jsfect*des*pwd";// 用户要求保存于keystore文件中的密码
String password = "decryp pwd";
javax.crypto.SecretKey mySecretKey = new SecretKeySpec(desPwd.getBytes(), "JKS");
KeyStore.SecretKeyEntry skEntry = new KeyStore.SecretKeyEntry(mySecretKey);
keyStore.setEntry("desPws", skEntry, new KeyStore.PasswordProtection(password.toCharArray()));
//将此 keystore 存储到给定输出流,并用给定密码保护其完整性。
os = new FileOutputStream("D:/csdn_server.keystore");
keyStore.store(os, storepass.toCharArray());
os.close();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (UnrecoverableEntryException e) {
e.printStackTrace();
} finally {
try {
if(os != null)
os.close();
if (fis != null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3、取出保存的密码
package test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
/**
* 从keystore文件中取出密码
*/
public class KeyStoreUtil {
public static void main(String[] args) {
String storepass = "888999";
try {
FileInputStream fis = null;
// 读取keystore文件转换为keystore密钥库对象
fis = new FileInputStream("D:/csdn_server.keystore");
// 因为生成证书的类型为JKS 也有其他的格式
KeyStore keyStore = KeyStore.getInstance("jceks");
// 该密钥库的密码"888999",storepass指定密钥库的密码(获取keystore信息所需的密码)
keyStore.load(fis, storepass.toCharArray());
fis.close();
String password = "decryp pwd";
// 根据别名(alias=desPws)从证书(keyStore)获取密码并解密
//keyStore.getKey返回与给定别名关联的密钥,并用给定密码来恢复它。
Key key = keyStore.getKey("desPws", password.toCharArray());
//key.getEncoded()返回基本编码格式的密钥,如果此密钥不支持编码,则返回 null。
System.out.println("从证书中获取的解密密码是:" + new String(key.getEncoded()));
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (CertificateException e) {
e.printStackTrace();
}
}
}