今天来点实际工作中的硬通货!
与计费系统打交道,少不了用到加密/解密实现。为了安全起见,通过非对称加密交换对称加密密钥更是不可或缺。那么需要通过什么载体传递非对称算法公钥/私钥信息?数字证书是公钥的载体,而密钥库可以包含公钥、私钥信息。
JKS和
PKCS#12都是比较常用的两种密钥库格式/标准。对于前者,搞Java开发,尤其是接触过HTTPS平台的朋友,并不陌生。
JKS文件(通常为*.jks或*.keystore,扩展名无关)可以通过Java原生工具——KeyTool生成;而后者
PKCS#12文件(通常为*.p12或*.pfx,意味个人信息交换文件),则是通过更为常用的OpenSSL工具产生。
当然,这两者之间是可以通过导入/导出的方式进行转换的!当然,这种转换需要通过KeyTool工具进行!
回归正题,计费同事遇到一个难题:合作方交给他们一个*.pfx文件,需要他们从中提取密钥,然后进行加密交互。其实,通过Java直接操作密钥库文件(或个人信息交换文件)对于一般Java开发人员来说,这都是个冷门。不接触数字安全,根本不知所云。况且,Java原生的密钥库文件格式为JKS,如何操作*.pfx文件?密钥库操作需要获知密钥库别名,*.pfx别名是什么?!接下来就解决这些问题!
方案:
- 通过keytool密钥库导入命令importkeystore,将密钥库格式由PKCS#12转换为JKS。
- 检索新生成的密钥库文件,提取别名信息。
- 由密钥库文件导出数字证书(这里将用到别名)。
- 通过代码提取公钥/私钥、签名算法等
先看格式转换:
-
echo格式转换
-
keytool-importkeystore-v-srckeystorezlex.pfx-srcstoretypepkcs12-srcstorepass123456-destkeystorezlex.keystore-deststoretypejks-deststorepass123456
-importkeystore导入密钥库,通过格式设定,我们可以将PKCS#12文件转换为JKS格式。
-v显示详情
-srckeystore源密钥库,这里是zlex.pfx
-srcstoretype源密钥库格式,这里为pkcs12
-srcstorepass源密钥库密码,这里为123456
-destkeystore目标密钥库,这里为zlex.keystore
-deststoretype目标密钥库格式,这里为jks,默认值也如此
-deststorepass目标密钥库密码,这里为123456
通过这个操作,我们能够获得所需的密钥库文件zlex.keystore。
这时,我们已经获得了密钥库文件,只要确定对应的别名信息,就可以提取公钥/私钥,以及数字证书,进行加密交互了!
-
echo查看证书
-
keytool-list-keystorezlex.keystore-storepass123456-v
-list列举密钥库
-keystore密钥库,这里是zlex.keystore
-storepass密钥库密码,这里是123456
-v显示详情
这里需要细致观察一下别名信息!!!就是红框中的数字1!!!
现在,我们把证书导出!
-
echo导出证书
-
keytool-exportcert-alias1-keystorezlex.keystore-filezlex.crt-storepass123456
-exportcert导出证书
-alias别名,这里是1
-keystore密钥库,这里是zlex.keystore
-file证书文件,这里是zlex.crt
-storepass密钥库密码,这里是123456
现在证书也导出了,我们可以提取公钥/私钥,进行加密/解密,签名/验证操作了!当然,即便没有证书,我们也能够通过密钥库(JKS格式)文件获得证书,以及公钥/私钥、签名算法等。
补充代码, 其实就是对
Java加密技术(八)的修改!
-
-
-
-
-
importjava.io.FileInputStream;
-
importjava.security.KeyStore;
-
importjava.security.PrivateKey;
-
importjava.security.PublicKey;
-
importjava.security.Signature;
-
importjava.security.cert.Certificate;
-
importjava.security.cert.CertificateFactory;
-
importjava.security.cert.X509Certificate;
-
importjava.util.Date;
-
-
importjavax.crypto.Cipher;
-
-
-
-
-
-
-
-
publicclassCertificateCoder{
-
-
-
-
publicstaticfinalStringKEY_STORE="JKS";
-
-
publicstaticfinalStringX509="X.509";
-
-
-
-
-
-
-
-
-
-
-
-
privatestaticPrivateKeygetPrivateKey(StringkeyStorePath,
-
StringkeyStorePassword,Stringalias,StringaliasPassword)
-
throwsException{
-
KeyStoreks=getKeyStore(keyStorePath,keyStorePassword);
-
PrivateKeykey=(PrivateKey)ks.getKey(alias,
-
aliasPassword.toCharArray());
-
returnkey;
-
}
-
-
-
-
-
-
-
-
-
privatestaticPublicKeygetPublicKey(StringcertificatePath)
-
throwsException{
-
Certificatecertificate=getCertificate(certificatePath);
-
PublicKeykey=certificate.getPublicKey();
-
returnkey;
-
}
-
-
-
-
-
-
-
-
-
privatestaticCertificategetCertificate(StringcertificatePath)
-
throwsException{
-
CertificateFactorycertificateFactory=CertificateFactory
-
.getInstance(X509);
-
FileInputStreamin=newFileInputStream(certificatePath);
-
-
Certificatecertificate=certificateFactory.generateCertificate(in);
-
in.close();
-
-
returncertificate;
-
}
-
-
-
-
-
-
-
-
-
-
-
privatestaticCertificategetCertificate(StringkeyStorePath,
-
StringkeyStorePassword,Stringalias)throwsException{
-
KeyStoreks=getKeyStore(keyStorePath,keyStorePassword);
-
Certificatecertificate=ks.getCertificate(alias);
-
-
returncertificate;
-
}
-
-
-
-
-
-
-
-
-
-
privatestaticKeyStoregetKeyStore(StringkeyStorePath,Stringpassword)
-
throwsException{
-
FileInputStreamis=newFileInputStream(keyStorePath);
-
KeyStoreks=KeyStore.getInstance(KEY_STORE);
-
ks.load(is,password.toCharArray());
-
is.close();
-
returnks;
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
publicstaticbyte[]encryptByPrivateKey(byte[]data,StringkeyStorePath,
-
StringkeyStorePassword,Stringalias,StringaliasPassword)
-
throwsException{
-
-
PrivateKeyprivateKey=getPrivateKey(keyStorePath,keyStorePassword,
-
alias,aliasPassword);
-
-
-
Ciphercipher=Cipher.getInstance(privateKey.getAlgorithm());
-
cipher.init(Cipher.ENCRYPT_MODE,privateKey);
-
-
returncipher.doFinal(data);
-
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
publicstaticbyte[]decryptByPrivateKey(byte[]data,StringkeyStorePath,
-
Stringalias,StringkeyStorePassword,StringaliasPassword)
-
throwsException{
-
-
PrivateKeyprivateKey=getPrivateKey(keyStorePath,keyStorePassword,
-
alias,aliasPassword);
-
-
-
Ciphercipher=Cipher.getInstance(privateKey.getAlgorithm());
-
cipher.init(Cipher.DECRYPT_MODE,privateKey);
-
-
returncipher.doFinal(data);
-
-
}
-
-
-
-
-
-
-
-
-
-
publicstaticbyte[]encryptByPublicKey(byte[]data,StringcertificatePath)
-
throwsException{
-
-
-
PublicKeypublicKey=getPublicKey(certificatePath);
-
-
Ciphercipher=Cipher.getInstance(publicKey.getAlgorithm());
-
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
-
-
returncipher.doFinal(data);
-
-
}
-
-
-
-
-
-
-
-
-
-
publicstaticbyte[]decryptByPublicKey(byte[]data,StringcertificatePath)
-
throwsException{
-
-
PublicKeypublicKey=getPublicKey(certificatePath);
-
-
-
Ciphercipher=Cipher.getInstance(publicKey.getAlgorithm());
-
cipher.init(Cipher.DECRYPT_MODE,publicKey);
-
-
returncipher.doFinal(data);
-
-
}
-
-
-
-
-
-
-
-
publicstaticbooleanverifyCertificate(StringcertificatePath){
-
returnverifyCertificate(newDate(),certificatePath);
-
}
-
-
-
-
-
-
-
-
-
publicstaticbooleanverifyCertificate(Datedate,StringcertificatePath){
-
booleanstatus=true;
-
try{
-
-
Certificatecertificate=getCertificate(certificatePath);
-
-
status=verifyCertificate(date,certificate);
-
}catch(Exceptione){
-
status=false;
-
}
-
returnstatus;
-
}
-
-
-
-
-
-
-
-
-
privatestaticbooleanverifyCertificate(Datedate,Certificatecertificate){
-
booleanstatus=true;
-
try{
-
X509Certificatex509Certificate=(X509Certificate)certificate;
-
x509Certificate.checkValidity(date);
-
}catch(Exceptione){
-
status=false;
-
}
-
returnstatus;
-
}
-
-
-
-
-
-
-
-
-
-
-
-
publicstaticbyte[]sign(byte[]sign,StringkeyStorePath,Stringalias,
-
StringkeyStorePassword,StringaliasPassword)throwsException{
-
-
X509Certificatex509Certificate=(X509Certificate)getCertificate(
-
keyStorePath,keyStorePassword,alias);
-
-
-
PrivateKeyprivateKey=getPrivateKey(keyStorePath,keyStorePassword,
-
alias,aliasPassword);
-
-
-
Signaturesignature=Signature.getInstance(x509Certificate
-
.getSigAlgName());
-
signature.initSign(privateKey);
-
signature.update(sign);
-
returnsignature.sign();
-
}
-
-
-
-
-
-
-
-
-
-
-
publicstaticbooleanverify(byte[]data,byte[]sign,
-
StringcertificatePath)throwsException{
-
-
X509Certificatex509Certificate=(X509Certificate)getCertificate(certificatePath);
-
-
PublicKeypublicKey=x509Certificate.getPublicKey();
-
-
Signaturesignature=Signature.getInstance(x509Certificate
-
.getSigAlgName());
-
signature.initVerify(publicKey);
-
signature.update(data);
-
-
returnsignature.verify(sign);
-
-
}
-
-
-
-
-
-
-
-
-
-
publicstaticbooleanverifyCertificate(Datedate,StringkeyStorePath,
-
StringkeyStorePassword,Stringalias){
-
booleanstatus=true;
-
try{
-
Certificatecertificate=getCertificate(keyStorePath,
-
keyStorePassword,alias);
-
status=verifyCertificate(date,certificate);
-
}catch(Exceptione){
-
status=false;
-
}
-
returnstatus;
-
}
-
-
-
-
-
-
-
-
-
-
publicstaticbooleanverifyCertificate(StringkeyStorePath,
-
StringkeyStorePassword,Stringalias){
-
returnverifyCertificate(newDate(),keyStorePath,keyStorePassword,
-
alias);
-
}
-
}
相信上述代码已经帮朋友们解决了相当多的问题!
给出测试类:
-
importstaticorg.junit.Assert.*;
-
-
importjava.util.Date;
-
-
importorg.apache.commons.codec.binary.Hex;
-
importorg.junit.Test;
-
-
-
-
-
-
-
-
-
publicclassCertificateCoderTest{
-
privateStringcertificatePath="zlex.crt";
-
privateStringkeyStorePath="zlex.keystore";
-
privateStringkeyStorePassword="123456";
-
privateStringaliasPassword="123456";
-
privateStringalias="1";
-
-
@Test
-
publicvoidtest()throwsException{
-
System.err.println("公钥加密——私钥解密");
-
StringinputStr="Ceritifcate";
-
byte[]data=inputStr.getBytes();
-
-
byte[]encrypt=CertificateCoder.encryptByPublicKey(data,
-
certificatePath);
-
-
byte[]decrypt=CertificateCoder.decryptByPrivateKey(encrypt,
-
keyStorePath,alias,keyStorePassword,aliasPassword);
-
StringoutputStr=newString(decrypt);
-
-
System.err.println("加密前:"+inputStr+"\n\r"+"解密后:"+outputStr);
-
-
-
assertArrayEquals(data,decrypt);
-
-
-
assertTrue(CertificateCoder.verifyCertificate(certificatePath));
-
-
}
-
-
@Test
-
publicvoidtestSign()throwsException{
-
System.err.println("私钥加密——公钥解密");
-
-
StringinputStr="sign";
-
byte[]data=inputStr.getBytes();
-
-
byte[]encodedData=CertificateCoder.encryptByPrivateKey(data,
-
keyStorePath,keyStorePassword,alias,aliasPassword);
-
-
byte[]decodedData=CertificateCoder.decryptByPublicKey(encodedData,
-
certificatePath);
-
-
StringoutputStr=newString(decodedData);
-
System.err.println("加密前:"+inputStr+"\n\r"+"解密后:"+outputStr);
-
assertEquals(inputStr,outputStr);
-
-
System.err.println("私钥签名——公钥验证签名");
-
-
byte[]sign=CertificateCoder.sign(encodedData,keyStorePath,alias,
-
keyStorePassword,aliasPassword);
-
System.err.println("签名:\r"+Hex.encodeHexString(sign));
-
-
-
booleanstatus=CertificateCoder.verify(encodedData,sign,
-
certificatePath);
-
System.err.println("状态:\r"+status);
-
assertTrue(status);
-
}
-
-
@Test
-
publicvoidtestVerify()throwsException{
-
System.err.println("密钥库证书有效期验证");
-
booleanstatus=CertificateCoder.verifyCertificate(newDate(),
-
keyStorePath,keyStorePassword,alias);
-
System.err.println("证书状态:\r"+status);
-
assertTrue(status);
-
}
-
}
第一个测试方法,用于提取公钥/私钥进行加密/解密操作。
第二个测试方法,用于提取签名算法进行签名/验证操作。
第三个测试方法,用于测试密钥库该别名对应的证书,当前日期下,是否有效。
OK,任务完成,密钥成功提取,剩下的都是代码基本功了!
分享到:
相关推荐
Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC Java加密技术(二)——对称加密算法DES&AES Java加密技术(三)——PBE算法 Java加密技术(四)...Java加密技术(十二)——*.PFX(*.p12)&个人信息交换文件
Java KeyStore文件转换为微软的.pfx文件和OpenSSL的PEM格式文件(.key + .crt) 运行方式: JKS2PFX 文件> 密码> 别名> <导出文件名> [Java Runtime的目录] Java Runtime的目录,指包含Java.exe和keytool.exe的目录...
修改PFX证书使用时间,临时使用时间,延长SSL证书时间
这一步就不详细说了,有免费的和收费的,申请完成之后会给你一个*.pfx结尾的文件。 添加NuGet包 nuget中查找然后再程序中添加引用Microsoft.AspNetCore.Server.Kestrel.Https 配置 把*.pfx结尾的文件...
c# RSA读取密钥文件pfx cer 签名验签加密解密工具类 1 包含java形式密钥转换成c# c# 形式密钥转换成java
java 生成的有私钥的证书导入IE,或者把IE导出的证书导入java的KeyStore
java rsa证书加密,crt、pem、pfx、cer等 内附工具
pfx证书一键生成 压缩文档内有详细说明,利用批处理便捷的生成pfx证书.
将jks文件生成pfx文件的工具,亲测可以使用。 例如: JKS2PFX server.jks 123456 tomcat exportfile c:\progra~1\Java\jre1.5.0_06\bin 该命令将server.jks中别名为tomcat的SSL证书导出,运行后将产生3个文件 ...
makecert -r -pe -n ...pvk2pfx -pvk ServerPublicKey.pvk -spc ServerPublicKey.cer -pfx ServerPrivateKey.pfx -pi password makecert.exe pvk2pfx.exe
.arch图书馆系统_TemporaryKey.pfx
PFX to CER(PFX批量转换成CER)
主要介绍了Node.js中.pfx后缀文件的处理方法,文中介绍的很详细,对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。
PfxCreator PEM证书+私钥-> PFXPfxCreator是一个简单的单exe工具,用于根据证书和私钥的PEM表示创建PKCS#12文件(.pfx,.p12)。 无需安装或依赖文件。 PfxCreator的工作简单明了,在许多需要将证书导入Microsoft...
nt5src最新driver.pfx(testroot)证书,有效期至2122年;修正了 pfx 空密码时提示密码不正确等问题。
NULL 博文链接:https://mimmy.iteye.com/blog/520604
开发技术使用RSA非对称加密,一键生成pfx证书工具,内附 文档说明。
pfx蛮力 PfxBruteForce是一个简单的C#工具,它试图破解* .p12或* .pfx文件上的简单密码。 它会尝试给定长度的所有可能的密码组合。 有关它的原始博客文章位于