DSADigital Signature Algorithm(Schnorr和ElGamal签名算法的变种)

  1 package com.ice.webos.util.security;
2
3 import java.security.Key;
4 import java.security.KeyFactory;
5 import java.security.KeyPair;
6 import java.security.KeyPairGenerator;
7 import java.security.PrivateKey;
8 import java.security.PublicKey;
9 import java.security.SecureRandom;
10 import java.security.Signature;
11 import java.security.interfaces.DSAPrivateKey;
12 import java.security.interfaces.DSAPublicKey;
13 import java.security.spec.PKCS8EncodedKeySpec;
14 import java.security.spec.X509EncodedKeySpec;
15 import java.util.HashMap;
16 import java.util.Map;
17
18 /**
19 * DSA-Digital Signature Algorithm
20 * 是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。<br>
21 * 简单的说,这是一种更高级的验证方式,用作数字签名。<br>
22 * 不单单只有公钥、私钥,还有数字签名。私钥加密生成数字签名,公钥验证数据及签名。<br>
23 * 如果数据和签名不匹配则认为验证失败!数字签名的作用就是校验数据在传输过程中不被修改。<br>
24 * 数字签名,是单向加密的升级!
25 *
26 * @author Ice_Liu
27 *
28 */
29 public class DSACryptUtil {
30
31 public static final String ALGORITHM = "DSA";
32
33 /**
34 * 默认密钥字节数
35 *
36 * <pre>
37 *
38 * DSA
39 * Default Keysize 1024
40 * Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive).
41 * </pre>
42 */
43 private static final int KEY_SIZE = 1024;
44
45 /**
46 * 默认种子
47 */
48 private static final String DEFAULT_SEED = "0f22507a10bbddd07d8a3082122966e3";
49
50 private static final String PUBLIC_KEY = "DSAPublicKey";
51 private static final String PRIVATE_KEY = "DSAPrivateKey";
52
53 /**
54 * 用私钥对信息生成数字签名
55 *
56 * @param data
57 * 加密数据
58 * @param privateKey
59 * 私钥
60 *
61 * @return
62 * @throws Exception
63 */
64 public static String sign(byte[] data, String privateKey) throws Exception {
65 // 解密由base64编码的私钥
66 byte[] keyBytes = CryptUtil.decryptBASE64(privateKey);
67
68 // 构造PKCS8EncodedKeySpec对象
69 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
70
71 // KEY_ALGORITHM 指定的加密算法
72 KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
73
74 // 取私钥匙对象
75 PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
76
77 // 用私钥对信息生成数字签名
78 Signature signature = Signature.getInstance(keyFactory.getAlgorithm());
79 signature.initSign(priKey);
80 signature.update(data);
81
82 return CryptUtil.encryptBASE64(signature.sign());
83 }
84
85 /**
86 * 校验数字签名
87 *
88 * @param data
89 * 加密数据
90 * @param publicKey
91 * 公钥
92 * @param sign
93 * 数字签名
94 *
95 * @return 校验成功返回true 失败返回false
96 * @throws Exception
97 *
98 */
99 public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
100
101 // 解密由base64编码的公钥
102 byte[] keyBytes = CryptUtil.decryptBASE64(publicKey);
103
104 // 构造X509EncodedKeySpec对象
105 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
106
107 // ALGORITHM 指定的加密算法
108 KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
109
110 // 取公钥匙对象
111 PublicKey pubKey = keyFactory.generatePublic(keySpec);
112
113 Signature signature = Signature.getInstance(keyFactory.getAlgorithm());
114 signature.initVerify(pubKey);
115 signature.update(data);
116
117 // 验证签名是否正常
118 return signature.verify(CryptUtil.decryptBASE64(sign));
119 }
120
121 /**
122 * 生成密钥
123 *
124 * @param seed
125 * 种子
126 * @return 密钥对象
127 * @throws Exception
128 */
129 public static Map<String, Object> initKey(String seed) throws Exception {
130 KeyPairGenerator keygen = KeyPairGenerator.getInstance(ALGORITHM);
131 // 初始化随机产生器
132 SecureRandom secureRandom = new SecureRandom();
133 secureRandom.setSeed(seed.getBytes());
134 keygen.initialize(KEY_SIZE, secureRandom);
135
136 KeyPair keys = keygen.genKeyPair();
137
138 DSAPublicKey publicKey = (DSAPublicKey) keys.getPublic();
139 DSAPrivateKey privateKey = (DSAPrivateKey) keys.getPrivate();
140
141 Map<String, Object> map = new HashMap<String, Object>(2);
142 map.put(PUBLIC_KEY, publicKey);
143 map.put(PRIVATE_KEY, privateKey);
144
145 return map;
146 }
147
148 /**
149 * 默认生成密钥
150 *
151 * @return 密钥对象
152 * @throws Exception
153 */
154 public static Map<String, Object> initKey() throws Exception {
155 return initKey(DEFAULT_SEED);
156 }
157
158 /**
159 * 取得私钥
160 *
161 * @param keyMap
162 * @return
163 * @throws Exception
164 */
165 public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
166 Key key = (Key) keyMap.get(PRIVATE_KEY);
167
168 return CryptUtil.encryptBASE64(key.getEncoded());
169 }
170
171 /**
172 * 取得公钥
173 *
174 * @param keyMap
175 * @return
176 * @throws Exception
177 */
178 public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
179 Key key = (Key) keyMap.get(PUBLIC_KEY);
180
181 return CryptUtil.encryptBASE64(key.getEncoded());
182 }
183
184 public static void main(String[] args) {
185 try {
186 DHCryptUtil.main(args);
187 System.out.println("************************************");
188 System.out.println("DSA 加密与解密");
189 String inputStr = "abc";
190 byte[] data = inputStr.getBytes();
191
192 // 构建密钥
193 Map<String, Object> keyMap = DSACryptUtil.initKey();
194 // 获得密钥
195 String publicKey = DSACryptUtil.getPublicKey(keyMap);
196 String privateKey = DSACryptUtil.getPrivateKey(keyMap);
197
198 System.err.println("公钥:\r" + publicKey);
199 System.err.println("私钥:\r" + privateKey);
200
201 // 产生签名
202 String sign = DSACryptUtil.sign(data, privateKey);
203 System.err.println("签名:\r" + sign);
204
205 // 验证签名
206 boolean status = DSACryptUtil.verify(data, publicKey, sign);
207 System.err.println("状态:\r" + status);
208
209 } catch (Exception e) {
210 e.printStackTrace();
211 }
212
213 }
214
215 }
原文地址:https://www.cnblogs.com/liubin0509/p/2331071.html