每日一步Java加密技术四.docx
《每日一步Java加密技术四.docx》由会员分享,可在线阅读,更多相关《每日一步Java加密技术四.docx(33页珍藏版)》请在冰豆网上搜索。
![每日一步Java加密技术四.docx](https://file1.bdocx.com/fileroot1/2023-2/23/17820183-84a5-4d13-aac9-0197d3552995/17820183-84a5-4d13-aac9-0197d35529951.gif)
每日一步Java加密技术四
ECC
ECC-EllipticCurvesCryptography,椭圆曲线密码编码学,是目前已知的公钥体制中,对每比特所提供加密强度最高的一种体制。
在软件注册保护方面起到很大的作用,一般的序列号通常由该算法产生。
当我开始整理《Java加密技术
(二)》的时候,我就已经在开始研究ECC了,但是关于Java实现ECC算法的资料实在是太少了,无论是国内还是国外的资料,无论是官方还是非官方的解释,最终只有一种答案——ECC算法在jdk1.5后加入支持,目前仅仅只能完成密钥的生成与解析。
如果想要获得ECC算法实现,需要调用硬件完成加密/解密(ECC算法相当耗费资源,如果单纯使用CPU进行加密/解密,效率低下),涉及到JavaCard领域,PKCS#11。
其实,PKCS#11配置很简单,但缺乏硬件设备,无法尝试!
尽管如此,我照旧提供相应的Java实现代码,以供大家参考。
通过java代码实现如下:
Java代码
1importjava.math.BigInteger;
2importjava.security.Key;
3importjava.security.KeyFactory;
4importjava.security.interfaces.ECPrivateKey;
5importjava.security.interfaces.ECPublicKey;
6importjava.security.spec.ECFieldF2m;
7importjava.security.spec.ECParameterSpec;
8importjava.security.spec.ECPoint;
9importjava.security.spec.ECPrivateKeySpec;
10importjava.security.spec.ECPublicKeySpec;
11importjava.security.spec.EllipticCurve;
12importjava.security.spec.PKCS8EncodedKeySpec;
13importjava.security.spec.X509EncodedKeySpec;
14importjava.util.HashMap;
15importjava.util.Map;
16
17importjavax.crypto.Cipher;
18importjavax.crypto.NullCipher;
19
20importsun.security.ec.ECKeyFactory;
21importsun.security.ec.ECPrivateKeyImpl;
22importsun.security.ec.ECPublicKeyImpl;
23
24/**
25*ECC安全编码组件
26*
27*@author梁栋
28*@version1.0
29*@since1.0
30*/
31publicabstractclassECCCoderextendsCoder{
32
33publicstaticfinalStringALGORITHM="EC";
34privatestaticfinalStringPUBLIC_KEY="ECCPublicKey";
35privatestaticfinalStringPRIVATE_KEY="ECCPrivateKey";
36
37/**
38*解密
39*用私钥解密
40*
41*@paramdata
42*@paramkey
43*@return
44*@throwsException
45*/
46publicstaticbyte[]decrypt(byte[]data,Stringkey)throwsException{
47//对密钥解密
48byte[]keyBytes=decryptBASE64(key);
49
50//取得私钥
51PKCS8EncodedKeySpecpkcs8KeySpec=newPKCS8EncodedKeySpec(keyBytes);
52KeyFactorykeyFactory=ECKeyFactory.INSTANCE;
53
54ECPrivateKeypriKey=(ECPrivateKey)keyFactory
55.generatePrivate(pkcs8KeySpec);
56
57ECPrivateKeySpececPrivateKeySpec=newECPrivateKeySpec(priKey.getS(),
58priKey.getParams());
59
60//对数据解密
61//TODOChipher不支持EC算法未能实现
62Ciphercipher=newNullCipher();
63//Cipher.getInstance(ALGORITHM,keyFactory.getProvider());
64cipher.init(Cipher.DECRYPT_MODE,priKey,ecPrivateKeySpec.getParams());
65
66returncipher.doFinal(data);
67}
68
69/**
70*加密
71*用公钥加密
72*
73*@paramdata
74*@paramprivateKey
75*@return
76*@throwsException
77*/
78publicstaticbyte[]encrypt(byte[]data,StringprivateKey)
79throwsException{
80//对公钥解密
81byte[]keyBytes=decryptBASE64(privateKey);
82
83//取得公钥
84X509EncodedKeySpecx509KeySpec=newX509EncodedKeySpec(keyBytes);
85KeyFactorykeyFactory=ECKeyFactory.INSTANCE;
86
87ECPublicKeypubKey=(ECPublicKey)keyFactory
88.generatePublic(x509KeySpec);
89
90ECPublicKeySpececPublicKeySpec=newECPublicKeySpec(pubKey.getW(),
91pubKey.getParams());
92
93//对数据加密
94//TODOChipher不支持EC算法未能实现
95Ciphercipher=newNullCipher();
96//Cipher.getInstance(ALGORITHM,keyFactory.getProvider());
97cipher.init(Cipher.ENCRYPT_MODE,pubKey,ecPublicKeySpec.getParams());
98
99returncipher.doFinal(data);
100}
101
102/**
103*取得私钥
104*
105*@paramkeyMap
106*@return
107*@throwsException
108*/
109publicstaticStringgetPrivateKey(MapkeyMap)
110throwsException{
111Keykey=(Key)keyMap.get(PRIVATE_KEY);
112
113returnencryptBASE64(key.getEncoded());
114}
115
116/**
117*取得公钥
118*
119*@paramkeyMap
120*@return
121*@throwsException
122*/
123publicstaticStringgetPublicKey(MapkeyMap)
124throwsException{
125Keykey=(Key)keyMap.get(PUBLIC_KEY);
126
127returnencryptBASE64(key.getEncoded());
128}
129
130/**
131*初始化密钥
132*
133*@return
134*@throwsException
135*/
136publicstaticMapinitKey()throwsException{
137BigIntegerx1=newBigInteger(
138"2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8",16);
139BigIntegerx2=newBigInteger(
140"289070fb05d38ff58321f2e800536d538ccdaa3d9",16);
141
142ECPointg=newECPoint(x1,x2);
143
144//theorderofgenerator
145BigIntegern=newBigInteger(
146"5846006549323611672814741753598448348329118574063",10);
147//thecofactor
148inth=2;
149intm=163;
150int[]ks={7,6,3};
151ECFieldF2mecField=newECFieldF2m(m,ks);
152//y^2+xy=x^3+x^2+1
153BigIntegera=newBigInteger("1",2);
154BigIntegerb=newBigInteger("1",2);
155
156EllipticCurveellipticCurve=newEllipticCurve(ecField,a,b);
157
158ECParameterSpececParameterSpec=newECParameterSpec(ellipticCurve,g,
159n,h);
160//公钥
161ECPublicKeypublicKey=newECPublicKeyImpl(g,ecParameterSpec);
162
163BigIntegers=newBigInteger(
164"1234006549323611672814741753598448348329118574063",10);
165//私钥
166ECPrivateKeyprivateKey=newECPrivateKeyImpl(s,ecParameterSpec);
167
168MapkeyMap=newHashMap
(2);
169
170keyMap.put(PUBLIC_KEY,publicKey);
171keyMap.put(PRIVATE_KEY,privateKey);
172
173returnkeyMap;
174}
175
176}
请注意上述代码中的TODO内容,再次提醒注意,Chipher不支持EC算法,以上代码仅供参考。
Chipher、Signature、KeyPairGenerator、KeyAgreement、SecretKey均不支持EC算法。
为了确保程序能够正常执行,我们使用了NullCipher类,验证程序。
照旧提供一个测试类:
Java代码
177importstaticorg.junit.Assert.*;
178
179importjava.math.BigInteger;
180importjava.security.spec.ECFieldF2m;
181importjava.security.spec.ECParameterSpec;
182importjava.security.spec.ECPoint;
183importjava.security.spec.ECPrivateKeySpec;
184importjava.security.spec.ECPublicKeySpec;
185importjava.security.spec.EllipticCurve;
186importjava.util.Map;
187
188importorg.junit.Test;
189
190/**
191*
192*@author梁栋
193*@version1.0
194*@since1.0
195*/
196publicclassECCCoderTest{
197
198@Test
199publicvoidtest()throwsException{
200StringinputStr="abc";
201byte[]data=inputStr.getBytes();
202
203MapkeyMap=ECCCoder.initKey();
204
205StringpublicKey=ECCCoder.getPublicKey(keyMap);
206StringprivateKey=ECCCoder.getPrivateKey(keyMap);
207System.err.println("公钥:
\n"+publicKey);
208System.err.println("私钥:
\n"+privateKey);
209
210byte[]encodedData=ECCCoder.encrypt(data,publicKey);
211
212byte[]decodedData=ECCCoder.decrypt(encodedData,privateKey);
213
214StringoutputStr=newString(decodedData);
215System.err.println("加密前:
"+inputStr+"\n\r"+"解密后:
"+outputStr);
216assertEquals(inputStr,outputStr);
217}
218}
控制台输出:
Console代码
219公钥:
220MEAwEAYHKoZIzj0CAQYFK4EEAAEDLAAEAv4TwFN7vBGsqgfXk95ObV5clO7oAokHD7BdOP9YMh8u
221gAU21TjM2qPZ
222
223私钥:
224MDICAQAwEAYHKoZIzj0CAQYFK4EEAAEEGzAZAgEBBBTYJsR3BN7TFw7JHcAHFkwNmfil7w==
225
226加密前:
abc
227
228解密后:
abc
本篇的主要内容为Java证书体系的实现。
请大家在阅读本篇内容时,预先了解RSA加密算法。
在构建Java代码实现前,我们需要完成证书的制作。
1.生成keyStroe文件
在命令行下执行以下命令:
Shell代码
229keytool-genkey-validity36000-aliaswww.zlex.org-keyalgRSA-keystored:
\zlex.keystore
其中
-genkey表示生成密钥
-validity指定证书有效期,这里是36000天
-alias指定别名,这里是www.zlex.org
-keyalg指定算法,这里是RSA
-keystore指定存储位置,这里是d:
\zlex.keystore
在这里我使用的密码为123456
控制台输出:
Console代码
230输入keystore密码:
231再次输入新密码:
232您的名字与姓氏是什么?
233[Unknown]:
www.zlex.org
234您的组织单位名称是什么?
235[Unknown]:
zlex
236您的组织名称是什么?
237[Unknown]:
zlex
238您所在的城市或区域名称是什么?
239[Unknown]:
BJ
240您所在的州或省份名称是什么?
241[Unknown]:
BJ
242该单位的两字母国家代码是什么
243[Unknown]:
CN
244CN=www.zlex.org,OU=zlex,O=zlex,L=BJ,ST=BJ,C=CN正确吗?
245[否]:
Y
246
247输入的主密码
248(如果和keystore密码相同,按回车):
249再次输入新密码:
这时,在D盘下会生成一个zlex.keystore的文件。
2.生成自签名证书
光有keyStore文件是不够的,还需要证书文件,证书才是直接提供给外界使用的公钥凭证。
导出证书:
Shell代码
250keytool-export-keystored:
\zlex.keystore-aliaswww.zlex.org-filed:
\zlex.cer-rfc
其中
-export指定为导出操作
-keystore指定keystore文件
-alias指定导出keystore文件中的别名
-file指向导出路径
-rfc以文本格式输出,也就是以BASE64编码输出
这里的密码是123456
控制台输出:
Console代码
251输入keystore密码:
252保存在文件中的认证\zlex.cer>
当然,使用方是需要导入证书的!
可以通过自签名证书完成CAS单点登录系统的构建!
Ok,准备工作完成,开始Java实现!
通过java代码实现如下:
Java代码
253importjava.io.FileInputStream;
254importjava.security.KeyStore;
255importjava.security.PrivateKey;
256importjava.security.PublicKey;
257importjava.security.Signature;
258importjava.security.cert.Certificate;
259importjava.security.cert.CertificateFactory;
260importjava.security.cert.X509Certificate;
261importjava.util.Date;
262
263importjavax.crypto.Cipher;
264
265/**
266*证书组件
267*
268*@author梁栋
269*@version1.0
270*@since1.0
271*/
272publicabstractclassCertificateCoderextendsCoder{
273
274
275/**
276*Java密钥库(JavaKeyStore,JKS)KEY_STORE
277*/
278publicstaticfinalStringKEY_STORE="JKS";
279
280publicstaticfinalStringX509="X.509";
281
282/**
283*由KeyStore获得私钥
284*
285*@paramkeyStorePath
286*@paramalias
287*@parampassword
288*@return
289*@throwsException
290*/
291privatestaticPrivateKeygetPrivateKey(StringkeyStorePath,Stringalias,
292Stringpassword)throwsException{
293KeyStoreks=getKeyStore(keyStorePath,password);
294PrivateKeykey=(PrivateKey)ks.getKey(alias,passwor