欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java结合keytool如何实现非对称加密与解密详解

程序员文章站 2024-02-23 22:39:04
前言 参考: 那一篇讲签名,这一篇将加密解密。在java安全体系中,签名属于jaas模块,加解密属于jce模块。 keytool的使用 keytool是jd...

前言

参考:

那一篇讲签名,这一篇将加密解密。在java安全体系中,签名属于jaas模块,加解密属于jce模块。

keytool的使用

keytool是jdk自带的一个密钥库管理工具。这里只用到了keytool的部分功能,包括生成密钥对,导出公钥等。keytool生成的公钥/私钥对存放到一个到了一个文件中,这个文件有密码保护,通称为keystore。

生成密钥对

$ keytool -genkey -alias signlegal -keystore examplestanstore2 -validity 1800 -keyalg rsa

生成别名为signlegal的密钥对,存放在密钥库examplestanstore2中,证书的有效期是1800天(默认是90天)。

输入一系列的参数。输入的参数遵循了ldap的风格和标准。可以想象,生成的密钥对可以看成ldap的一个条目。

命令执行成功后会在当前目录下创建一个叫examplestanstore2的文件。相对另一篇博文,增加了一个keyalg参数。因为keytool默认算法是dsa,而dsa只能用于签名。rsa既能用于签名,也能用于加密。而本文是研究加密问题,只能用rsa算法。

查看密钥对

$ keytool -list -keystore examplestanstore2 -v

列出了examplestanstore2密钥库的中所有密钥对。-v参数表示详细信息,详细信息中有证书的失效时间。

导出公钥证书

$ keytool -export -keystore examplestanstore2 -alias signlegal -file stansmith.crt -rfc

导出的公钥存放在当前目录的stansmith.crt文件中。讲“签名”的那篇博文没有加-rfc参数,导出是个二进制文件(cer格式)。

加上-rfc后,导出的是文本文件(pem)格式。在下面的测试中,如果使用cer格式,会报错 ` no installed provider supports this key: sun.security.provider.dsapublickeyimpl`。

java加密和解密


在java程序中,首先从密钥库取出私钥和公钥,然后对测试字符串进行加密。二进制的密文转换成字符串输出到屏幕,然后解密成明文再输出到屏幕。

gensig2.java

import java.io.*;
import java.security.keystore;
import java.security.privatekey;
import java.security.publickey;
import javax.crypto.cipher;
import sun.security.provider.*;


public class rsaentry {
 public static void main(string[] args) {
 try {
 //1.从密钥库中取私钥
 keystore ks = keystore.getinstance("jks");
 fileinputstream ksfis = new fileinputstream("examplestanstore2");
 bufferedinputstream ksbufin = new bufferedinputstream(ksfis);

 // open keystore and get private key
 // alias is 'signleal', kpasswd/spasswd is 'vagrant'
 ks.load(ksbufin, "vagrant".tochararray());
 privatekey prikey = (privatekey) ks.getkey("signlegal", "vagrant".tochararray());

 //2.根据命令行参数取公钥
 fileinputstream certfis = new fileinputstream(args[0]);
 java.security.cert.certificatefactory cf =
  java.security.cert.certificatefactory.getinstance("x.509");
 java.security.cert.certificate cert = cf.generatecertificate(certfis);
 publickey pubkey = cert.getpublickey();


 //3.使用公钥进行加密
 string data = "测试数据";
 //构建加密解密类
 cipher cipher = cipher.getinstance("rsa");
 cipher.init(cipher.encrypt_mode, pubkey);//设置为加密模式
 byte[] jmdata = cipher.dofinal(data.getbytes());
 //打印加密后数据
 system.out.println(bytestohexstring(jmdata));
 //改为解密模式进行解密
 cipher.init(cipher.decrypt_mode, prikey);//会用私钥解密
 jmdata = cipher.dofinal(jmdata);
 system.out.println(new string(jmdata));
 }catch (exception e) {
  e.printstacktrace();
 }
 }
 //这个方法用于把二进制转换成ascii字符串。
 public static string bytestohexstring(byte[] bytes) {
 if (bytes == null)
  return "null!";
 int len = bytes.length;
 stringbuilder ret = new stringbuilder(2 * len);

 for (int i = 0; i < len; ++i) {
  int b = 0xf & bytes[(i)] >> 4;
  ret.append("0123456789abcdef".charat(b));
  b = 0xf & bytes[(i)];
  ret.append("0123456789abcdef".charat(b));
 }

 return ret.tostring();
 }
}

编译,并运行:

$ javac rsaentry.java
$ java rsaentry stansmith.crt
8fceea48e34fdc786bde05459f3366714b650ff04f4e81e52eca139d8ee0b4acbcad019cd496de3589765894b2d5f4a2af38914af614d9e9b73e551ae01830cd6f49505685d7e527e3adc2b7a2a75608068627c0a12b338d3c743a5de2af2de327a0de14b548604e5c8905747aef077852ecfd2eb4a134ca0f3a56b23db8ae4beb07add5ba3725ab3ee0ffa7481494856144ba5004a329cfe2c43078f0cd95aebcbbfc6c1894efafacac90615e549cb8432c125d912a5e54ce4884f633f3e96bd7b61c1d538e38713716367f7ec6f5ca01288e6d96ad9e3d6515147369144390e1d002b1beaf5797966e3b498cc7def754816c99456ef380b3a83366a44415f6
测试数据

本文展示的算法是一种非对称算法,计算较慢。在ssl中,非对称算法用于客户端和服务器之间交换对称加密的一次性密钥。客户端将一个随机数用服务器的公钥加密发给服务器,如果服务器持有私钥,就能解开密文获得随机数(这个随机数就是对称算法的密钥)。有了对称算法密钥,双方就可以用对称加密进行安全通信了。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。