本文實例講述了基于java實現的ECC加密算法。分享給大家供大家參考,具體如下:
ECC
ECC-Elliptic Curves Cryptography,橢圓曲線密碼編碼學,是目前已知的公鑰體制中,對每比特所提供加密強度最高的一種體制。在軟件注冊保護方面起到很大的作用,一般的序列號通常由該算法產生。
當我開始整理《Java加密技術(二)》的時候,我就已經在開始研究ECC了,但是關于Java實現ECC算法的資料實在是太少了,無論是國內還是國外的 資料,無論是官方還是非官方的解釋,最終只有一種答案——ECC算法在jdk1.5后加入支持,目前僅僅只能完成密鑰的生成與解析。 如果想要獲得ECC算法實現,需要調用硬件完成加密/解密(ECC算法相當耗費資源,如果單純使用CPU進行加密/解密,效率低下),涉及到Java Card領域,PKCS#11。 其實,PKCS#11配置很簡單,但缺乏硬件設備,無法嘗試!
盡管如此,我照舊提供相應的Java實現代碼,以供大家參考。
通過java代碼實現如下:
Coder類:
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
import java.math.BigInteger; import java.security.Key; import java.security.KeyFactory; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.spec.ECFieldF2m; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.ECPrivateKeySpec; import java.security.spec.ECPublicKeySpec; import java.security.spec.EllipticCurve; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; import javax.crypto.Cipher; import javax.crypto.NullCipher; import sun.security.ec.ECKeyFactory; import sun.security.ec.ECPrivateKeyImpl; import sun.security.ec.ECPublicKeyImpl; /** * ECC安全編碼組件 * * @author 梁棟 * @version 1.0 * @since 1.0 */ public abstract class ECCCoder extends Coder { public static final String ALGORITHM = "EC" ; private static final String PUBLIC_KEY = "ECCPublicKey" ; private static final String PRIVATE_KEY = "ECCPrivateKey" ; /** * 解密<br> * 用私鑰解密 * * @param data * @param key * @return * @throws Exception */ public static byte [] decrypt( byte [] data, String key) throws Exception { // 對密鑰解密 byte [] keyBytes = decryptBASE64(key); // 取得私鑰 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = ECKeyFactory.INSTANCE; ECPrivateKey priKey = (ECPrivateKey) keyFactory .generatePrivate(pkcs8KeySpec); ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(priKey.getS(), priKey.getParams()); // 對數據解密 // TODO Chipher不支持EC算法 未能實現 Cipher cipher = new NullCipher(); // Cipher.getInstance(ALGORITHM, keyFactory.getProvider()); cipher.init(Cipher.DECRYPT_MODE, priKey, ecPrivateKeySpec.getParams()); return cipher.doFinal(data); } /** * 加密<br> * 用公鑰加密 * * @param data * @param privateKey * @return * @throws Exception */ public static byte [] encrypt( byte [] data, String privateKey) throws Exception { // 對公鑰解密 byte [] keyBytes = decryptBASE64(privateKey); // 取得公鑰 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = ECKeyFactory.INSTANCE; ECPublicKey pubKey = (ECPublicKey) keyFactory .generatePublic(x509KeySpec); ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(pubKey.getW(), pubKey.getParams()); // 對數據加密 // TODO Chipher不支持EC算法 未能實現 Cipher cipher = new NullCipher(); // Cipher.getInstance(ALGORITHM, keyFactory.getProvider()); cipher.init(Cipher.ENCRYPT_MODE, pubKey, ecPublicKeySpec.getParams()); return cipher.doFinal(data); } /** * 取得私鑰 * * @param keyMap * @return * @throws Exception */ public static String getPrivateKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PRIVATE_KEY); return encryptBASE64(key.getEncoded()); } /** * 取得公鑰 * * @param keyMap * @return * @throws Exception */ public static String getPublicKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PUBLIC_KEY); return encryptBASE64(key.getEncoded()); } /** * 初始化密鑰 * * @return * @throws Exception */ public static Map<String, Object> initKey() throws Exception { BigInteger x1 = new BigInteger( "2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8" , 16 ); BigInteger x2 = new BigInteger( "289070fb05d38ff58321f2e800536d538ccdaa3d9" , 16 ); ECPoint g = new ECPoint(x1, x2); // the order of generator BigInteger n = new BigInteger( "5846006549323611672814741753598448348329118574063" , 10 ); // the cofactor int h = 2 ; int m = 163 ; int [] ks = { 7 , 6 , 3 }; ECFieldF2m ecField = new ECFieldF2m(m, ks); // y^2+xy=x^3+x^2+1 BigInteger a = new BigInteger( "1" , 2 ); BigInteger b = new BigInteger( "1" , 2 ); EllipticCurve ellipticCurve = new EllipticCurve(ecField, a, b); ECParameterSpec ecParameterSpec = new ECParameterSpec(ellipticCurve, g, n, h); // 公鑰 ECPublicKey publicKey = new ECPublicKeyImpl(g, ecParameterSpec); BigInteger s = new BigInteger( "1234006549323611672814741753598448348329118574063" , 10 ); // 私鑰 ECPrivateKey privateKey = new ECPrivateKeyImpl(s, ecParameterSpec); Map<String, Object> keyMap = new HashMap<String, Object>( 2 ); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } } |
請注意上述代碼中的TODO內容,再次提醒注意,Chipher不支持EC算法 ,以上代碼僅供參考。Chipher、Signature、KeyPairGenerator、KeyAgreement、SecretKey均不支持EC算法。為了確保程序能夠正常執行,我們使用了NullCipher類,驗證程序。
照舊提供一個測試類:
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
|
import static org.junit.Assert.*; import java.math.BigInteger; import java.security.spec.ECFieldF2m; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.ECPrivateKeySpec; import java.security.spec.ECPublicKeySpec; import java.security.spec.EllipticCurve; import java.util.Map; import org.junit.Test; /** * * @author 梁棟 * @version 1.0 * @since 1.0 */ public class ECCCoderTest { @Test public void test() throws Exception { String inputStr = "abc" ; byte [] data = inputStr.getBytes(); Map<String, Object> keyMap = ECCCoder.initKey(); String publicKey = ECCCoder.getPublicKey(keyMap); String privateKey = ECCCoder.getPrivateKey(keyMap); System.err.println( "公鑰: \n" + publicKey); System.err.println( "私鑰: \n" + privateKey); byte [] encodedData = ECCCoder.encrypt(data, publicKey); byte [] decodedData = ECCCoder.decrypt(encodedData, privateKey); String outputStr = new String(decodedData); System.err.println( "加密前: " + inputStr + "\n\r" + "解密后: " + outputStr); assertEquals(inputStr, outputStr); } } |
控制臺輸出:
1
2
3
4
5
6
7
|
公鑰: MEAwEAYHKoZIzj0CAQYFK4EEAAEDLAAEAv4TwFN7vBGsqgfXk95ObV5clO7oAokHD7BdOP9YMh8u gAU21TjM2qPZ 私鑰: MDICAQAwEAYHKoZIzj0CAQYFK4EEAAEEGzAZAgEBBBTYJsR3BN7TFw7JHcAHFkwNmfil7w== 加密前: abc 解密后: abc |
本篇的主要內容為Java證書體系的實現。
希望本文所述對大家java程序設計有所幫助。
原文鏈接:http://blog.csdn.net/wjq008/article/details/49071827