- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
前言 。
参考:java结合keytool实现非对称签名与验证 。
那一篇讲签名,这一篇将加密解密。在java安全体系中,签名属于JAAS模块,加解密属于JCE模块.
keytool的使用 。
keytool是JDK自带的一个密钥库管理工具。这里只用到了keytool的部分功能,包括生成密钥对,导出公钥等。keytool生成的公钥/私钥对存放到一个到了一个文件中,这个文件有密码保护,通称为keystore.
生成密钥对 。
1
|
$ keytool -genkey -
alias
signLegal -keystore examplestanstore2 -validity 1800 -keyalg RSA
|
生成别名为signLegal的密钥对,存放在密钥库examplestanstore2中,证书的有效期是1800天(默认是90天).
输入一系列的参数。输入的参数遵循了LDAP的风格和标准。可以想象,生成的密钥对可以看成LDAP的一个条目.
命令执行成功后会在当前目录下创建一个叫examplestanstore2的文件。相对另一篇博文,增加了一个keyalg参数。因为keytool默认算法是DSA,而DSA只能用于签名。RSA既能用于签名,也能用于加密。而本文是研究加密问题,只能用RSA算法.
查看密钥对 。
1
|
$ keytool -list -keystore examplestanstore2 -
v
|
列出了examplestanstore2密钥库的中所有密钥对。-v参数表示详细信息,详细信息中有证书的失效时间.
导出公钥证书 。
1
|
$ 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 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
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();
}
}
|
编译,并运行:
1
2
3
4
|
$ javac RSAEntry.java
$ java RSAEntry StanSmith.crt
8fceea48e34fdc786bde05459f3366714b650ff04f4e81e52eca139d8ee0b4acbcad019cd496de3589765894b2d5f4a2af38914af614d9e9b73e551ae01830cd6f49505685d7e527e3adc2b7a2a75608068627c0a12b338d3c743a5de2af2de327a0de14b548604e5c8905747aef077852ecfd2eb4a134ca0f3a56b23db8ae4beb07add5ba3725ab3ee0ffa7481494856144ba5004a329cfe2c43078f0cd95aebcbbfc6c1894efafacac90615e549cb8432c125d912a5e54ce4884f633f3e96bd7b61c1d538e38713716367f7ec6f5ca01288e6d96ad9e3d6515147369144390e1d002b1beaf5797966e3b498cc7def754816c99456ef380b3a83366a44415f6
测试数据
|
本文展示的算法是一种非对称算法,计算较慢。在SSL中,非对称算法用于客户端和服务器之间交换对称加密的一次性密钥。客户端将一个随机数用服务器的公钥加密发给服务器,如果服务器持有私钥,就能解开密文获得随机数(这个随机数就是对称算法的密钥)。有了对称算法密钥,双方就可以用对称加密进行安全通信了.
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我的支持.
我是一名优秀的程序员,十分优秀!