java openssl_Java中使用OpenSSL生成的RSA公私钥进行数据加解密

本文介绍了如何在Java中利用OpenSSL生成RSA公私钥,并进行数据加密解密。首先,通过OpenSSL命令行生成PKCS#1格式的私钥和公钥,接着进行PKCS#8编码。然后,提供了Java代码实现加载密钥对,进行加密解密操作。此外,还展示了如何进行RSA签名和验签操作。
摘要由CSDN通过智能技术生成

当前使用的是Linux系统,已经按装使用OpenSSL软件包,

一、使用OpenSSL来生成私钥和公钥

1、执行命令openssl version -a 验证机器上已经安装openssl

运行结果:

ed91c5dd4d94c094702b0bbe9f0f17ae.png

2、生成私钥:这条命令让openssl随机生成了一份私钥,加密长度是1024位。加密长度是指理论上最大允许”被加密的信息“长度的限制,也就是明文的长度限制。随着这个参数的增大(比方说2048),允许的明文长度也会增加,但同时也会造成计算复杂度的极速增长。一般推荐的长度就是2048位

运行结果:

5c13e621e1019f0f94f70f334da8b1e5.png

生产私钥文件:rsa_private_key.pem,内容都是标准的ASCII字符,开头一行和结尾一行有明显的标记,真正的私钥数据是中间的不规则字符

bc39db1d7423d7589975e0123b77cdcd.png

3、根据私钥生产公钥:rsa_public_key.pem

运行结果:

d97afd9794012632e931e6ec466dba39.png

公钥内容:

0288c80e00e552e9fea86818af077a73.png

注意:此时的私钥还不能直接被使用,需要进行PKCS#8编码:

4、PKCS#8编码:指明输入私钥文件为rsa_private_key.pem,输出私钥文件为pkcs8_rsa_private_key.pem,不采用任何二次加密(-nocrypt)

至此:可用的密钥对已经生成好了,私钥使用pkcs8_rsa_private_key.pem,公钥采用rsa_public_key.pem

至此,可用的密钥对已经生成好了,私钥使用pkcs8_rsa_private_key.pem,公钥采用rsa_public_key.pem。

最近又遇到RSA加密的需求了,而且对方要求只能使用第一步生成的未经过PKCS#8编码的私钥文件。后来查看相关文献得知第一步生成的私钥文件编码是PKCS#1格式,这种格式Java其实是支持的,只不过多写两行代码而已:

48304ba5e6f9fe08f3fa1abda7d326ab.png

RSAPrivateKeyStructure asn1PrivKey = new RSAPrivateKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(priKeyData));

RSAPrivateKeySpec rsaPrivKeySpec = new RSAPrivateKeySpec(asn1PrivKey.getModulus(), asn1PrivKey.getPrivateExponent());

KeyFactory keyFactory= KeyFactory.getInstance("RSA");

PrivateKey priKey= keyFactory.generatePrivate(rsaPrivKeySpec);

48304ba5e6f9fe08f3fa1abda7d326ab.png

首先将PKCS#1的私钥文件读取出来(注意去掉减号开头的注释内容),然后使用Base64解码读出的字符串,便得到priKeyData,也就是第一行代码中的参数。最后一行得到了私钥。接下来的用法就没什么区别了。

二、编写Java代码实际测试

RSA加密解密类:

48304ba5e6f9fe08f3fa1abda7d326ab.png

1 import java.io.BufferedReader;

2 import java.io.BufferedWriter;

3 import java.io.FileReader;

4 import java.io.FileWriter;

5 import java.io.IOException;

6 import java.security.InvalidKeyException;

7 import java.security.KeyFactory;

8 import java.security.KeyPair;

9 import java.security.KeyPairGenerator;

10 import java.security.NoSuchAlgorithmException;

11 import java.security.SecureRandom;

12

13 import java.security.interfaces.RSAPrivateKey;

14 import java.security.interfaces.RSAPublicKey;

15 import java.security.spec.InvalidKeySpecException;

16 import java.security.spec.PKCS8EncodedKeySpec;

17 import java.security.spec.X509EncodedKeySpec;

18

19 import javax.crypto.BadPaddingException;

20 import javax.crypto.Cipher;

21 import javax.crypto.IllegalBlockSizeException;

22 import javax.crypto.NoSuchPaddingException;

23

24 import org.apache.commons.codec.binary.Base64;

25

26 public class RSAEncrypt {

27 /**

28 * 字节数据转字符串专用集合

29 */

30 private static final char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6',

31 '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

32

33 /**

34 * 随机生成密钥对

35 */

36 public static void genKeyPair(String filePath) {

37 // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象

38 KeyPairGenerator keyPairGen = null;

39 try {

40 keyPairGen = KeyPairGenerator.getInstance("RSA");

41 } catch (NoSuchAlgorithmException e) {

42 e.printStackTrace();

43 }

44 // 初始化密钥对生成器,密钥大小为96-1024位

45 keyPairGen.initialize(1024,new SecureRandom());

46 // 生成一个密钥对,保存在keyPair中

47 KeyPair keyPair = keyPairGen.generateKeyPair();

48 // 得到私钥

49 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

50 // 得到公钥

51 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

52 try {

53 // 得到公钥字符串

54 Base64 base64 = new Base64();

55 String publicKeyString = new String(base64.encode(publicKey.getEncoded()));

56 // 得到私钥字符串

57 String privateKeyString = new String(base64.encode(privateKey.getEncoded()));

58 // 将密钥对写入到文件

59 FileWriter pubfw = new FileWriter(filePath + "/publicKey.keystore");

60 FileWriter prifw = new FileWriter(filePath + "/privateKey.keystore");

61 BufferedWriter pubbw = new BufferedWriter(pubfw);

62 BufferedWriter pribw = new BufferedWriter(prifw);

63 pubbw.write(publicKeyString);

64 pribw.write(privateKeyString);

65 pubbw.flush();

66 pubbw.close();

67 pubfw.close();

68 pribw.flush();

69 pribw.close();

70 prifw.close();

71 } catch (Exception e) {

72 e.printStackTrace();

73 }

74 }

75

76 /**

77 * 从文件中输入流中加载公钥

78 *

79 * @param in

80 * 公钥输入流

81 * @throws Exception

82 * 加载公钥时产生的异常

83 */

84 public static String loadPublicKeyByFile(String path) throws Exception {

85 try {

86 BufferedReader br = new BufferedReader(new FileReader(path

87 + "/publicKey.keystore"));

88 String readLine = null;

89 StringBuilder sb = new StringBuilder();

90 while ((readLine = br.readLine()) != null) {

91 sb.append(readLine);

92 }

93 br.close();

94 return sb.toString();

95 } catch (IOException e) {

96 throw new Exception("公钥数据流读取错误");

97 } catch (NullPointerException e) {

98 throw new Exception("公钥输入流为空");

99 }

100 }

101

102 /**

103 * 从字符串中加载公钥

104 *

105 * @param publicKeyStr

106 * 公钥数据字符串

107 * @throws Exception

108 * 加载公钥时产生的异常

109 */

110 public static RSAPublicKey loadPublicKeyByStr(String publicKeyStr)

111 throws Exception {

112 try {

113 Base64 base64 = new Base64();

114 byte[] buffer = base64.decode(publicKeyStr);

115 KeyFactory keyFactory = KeyFactory.getInstance("RSA");

116 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);

117 return (RSAPublicKey) keyFactory.generatePublic(keySpec);

118 } catch (NoSuchAlgorithmException e) {

119 throw new Exception("无此算法");

120 } catch (InvalidKeySpecException e) {

121 throw new Exception("公钥非法");

122 } catch (NullPointerException e) {

123 throw new Exception("公钥数据为空");

124 }

125 }

126

127 /**

128 * 从文件中加载私钥

129 *

130 * @param keyFileName

131 * 私钥文件名

132 * @return 是否成功

133 * @throws Exception

134 */

135 public static String loadPrivateKeyByFile(String path) throws Exception {

136 try {

137 BufferedReader br = new BufferedReader(new FileReader(path

138 + "/privateKey.keystore"));

139 String readLine = null;

140 StringBuilder sb = new StringBuilder();

141 while ((readLine = br.readLine()) != null) {

142 sb.append(readLine);

143 }

144 br.close();

145 return sb.toString();

146 } catch (IOException e) {

147 throw new Exception("私钥数据读取错误");

148 } catch (NullPointerException e) {

149 throw new Exception("私钥输入流为空");

150 }

151 }

152

153 public static RSAPrivateKey loadPrivateKeyByStr(String privateKeyStr)

154 throws Exception {

155 try {

156 Base64 base64 = new Base64();

157 byte[] buffer = base64.decode(privateKeyStr);

158 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);

159 KeyFactory keyFactory = KeyFactory.getInstance("RSA");

160 return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);

161 } catch (NoSuchAlgorithmException e) {

162 throw new Exception("无此算法");

163 } catch (InvalidKeySpecException e) {

164 throw new Exception("私钥非法");

165 } catch (NullPointerException e) {

166 throw new Exception("私钥数据为空");

167 }

168 }

169

170 /**

171 * 公钥加密过程

172 *

173 * @param publicKey

174 * 公钥

175 * @param plainTextData

176 * 明文数据

177 * @return

178 * @throws Exception

179 * 加密过程中的异常信息

180 */

181 public static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData)

182 throws Exception {

183 if (publicKey == null) {

184 throw new Exception("加密公钥为空, 请设置");

185 }

186 Cipher cipher = null;

187 try {

188 // 使用默认RSA

189 cipher = Cipher.getInstance("RSA");

190 // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());

191 cipher.init(Cipher.ENCRYPT_MODE, publicKey);

192 byte[] output = cipher.doFinal(plainTextData);

193 return output;

194 } catch (NoSuchAlgorithmException e) {

195 throw new Exception("无此加密算法");

196 } catch (NoSuchPaddingException e) {

197 e.printStackTrace();

198 return null;

199 } catch (InvalidKeyException e) {

200 throw new Exception("加密公钥非法,请检查");

201 } catch (IllegalBlockSizeException e) {

202 throw new Exception("明文长度非法");

203 } catch (BadPaddingException e) {

204 throw new Exception("明文数据已损坏");

205 }

206 }

207

208 /**

209 * 私钥加密过程

210 *

211 * @param privateKey

212 * 私钥

213 * @param plainTextData

214 * 明文数据

215 * @return

216 * @throws Exception

217 * 加密过程中的异常信息

218 */

219 public static byte[] encrypt(RSAPrivateKey privateKey, byte[] plainTextData)

220 throws Exception {

221 if (privateKey == null) {

222 throw new Exception("加密私钥为空, 请设置");

223 }

224 Cipher cipher = null;

225 try {

226 // 使用默认RSA

227 cipher = Cipher.getInstance("RSA");

228 cipher.init(Cipher.ENCRYPT_MODE, privateKey);

229 byte[] output = cipher.doFinal(plainTextData);

230 return output;

231 } catch (NoSuchAlgorithmException e) {

232 throw new Exception("无此加密算法");

233 } catch (NoSuchPaddingException e) {

234 e.printStackTrace();

235 return null;

236 } catch (InvalidKeyException e) {

237 throw new Exception("加密私钥非法,请检查");

238 } catch (IllegalBlockSizeException e) {

239 throw new Exception("明文长度非法");

240 } catch (BadPaddingException e) {

241 throw new Exception("明文数据已损坏");

242 }

243 }

244

245 /**

246 * 私钥解密过程

247 *

248 * @param privateKey

249 * 私钥

250 * @param cipherData

251 * 密文数据

252 * @return 明文

253 * @throws Exception

254 * 解密过程中的异常信息

255 */

256 public static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData)

257 throws Exception {

258 if (privateKey == null) {

259 throw new Exception("解密私钥为空, 请设置");

260 }

261 Cipher cipher = null;

262 try {

263 // 使用默认RSA

264 cipher = Cipher.getInstance("RSA");

265 // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());

266 cipher.init(Cipher.DECRYPT_MODE, privateKey);

267 byte[] output = cipher.doFinal(cipherData);

268 return output;

269 } catch (NoSuchAlgorithmException e) {

270 throw new Exception("无此解密算法");

271 } catch (NoSuchPaddingException e) {

272 e.printStackTrace();

273 return null;

274 } catch (InvalidKeyException e) {

275 throw new Exception("解密私钥非法,请检查");

276 } catch (IllegalBlockSizeException e) {

277 throw new Exception("密文长度非法");

278 } catch (BadPaddingException e) {

279 throw new Exception("密文数据已损坏");

280 }

281 }

282

283 /**

284 * 公钥解密过程

285 *

286 * @param publicKey

287 * 公钥

288 * @param cipherData

289 * 密文数据

290 * @return 明文

291 * @throws Exception

292 * 解密过程中的异常信息

293 */

294 public static byte[] decrypt(RSAPublicKey publicKey, byte[] cipherData)

295 throws Exception {

296 if (publicKey == null) {

297 throw new Exception("解密公钥为空, 请设置");

298 }

299 Cipher cipher = null;

300 try {

301 // 使用默认RSA

302 cipher = Cipher.getInstance("RSA");

303 // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());

304 cipher.init(Cipher.DECRYPT_MODE, publicKey);

305 byte[] output = cipher.doFinal(cipherData);

306 return output;

307 } catch (NoSuchAlgorithmException e) {

308 throw new Exception("无此解密算法");

309 } catch (NoSuchPaddingException e) {

310 e.printStackTrace();

311 return null;

312 } catch (InvalidKeyException e) {

313 throw new Exception("解密公钥非法,请检查");

314 } catch (IllegalBlockSizeException e) {

315 throw new Exception("密文长度非法");

316 } catch (BadPaddingException e) {

317 throw new Exception("密文数据已损坏");

318 }

319 }

320

321 /**

322 * 字节数据转十六进制字符串

323 *

324 * @param data

325 * 输入数据

326 * @return 十六进制内容

327 */

328 public static String byteArrayToString(byte[] data) {

329 StringBuilder stringBuilder = new StringBuilder();

330 for (int i = 0; i < data.length; i++) {

331 // 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移

332 stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);

333 // 取出字节的低四位 作为索引得到相应的十六进制标识符

334 stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);

335 if (i < data.length - 1) {

336 stringBuilder.append(' ');

337 }

338 }

339 return stringBuilder.toString();

340 }

341 }

48304ba5e6f9fe08f3fa1abda7d326ab.png

签名及校验类:

48304ba5e6f9fe08f3fa1abda7d326ab.png

1 import java.security.KeyFactory;

2 import java.security.PrivateKey;

3 import java.security.PublicKey;

4 import java.security.spec.PKCS8EncodedKeySpec;

5 import java.security.spec.X509EncodedKeySpec;

6

7 import org.apache.commons.codec.binary.Base64;

8

9 /**

10 * RSA签名验签类

11 */

12 public class RSASignature {

13

14 /**

15 * 签名算法

16 */

17 public static final String SIGN_ALGORITHMS = "SHA1WithRSA";

18

19 /**

20 * RSA签名

21 *

22 * @param content

23 * 待签名数据

24 * @param privateKey

25 * 商户私钥

26 * @param encode

27 * 字符集编码

28 * @return 签名值

29 */

30 public static String sign(String content, String privateKey, String encode) {

31 try {

32 Base64 base64 = new Base64();

33 PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(base64.decode(privateKey));

34

35 KeyFactory keyf = KeyFactory.getInstance("RSA");

36 PrivateKey priKey = keyf.generatePrivate(priPKCS8);

37

38 java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

39

40 signature.initSign(priKey);

41 signature.update(content.getBytes(encode));

42

43 byte[] signed = signature.sign();

44

45 return new String(base64.encode(signed));

46 } catch (Exception e) {

47 e.printStackTrace();

48 }

49

50 return null;

51 }

52

53 public static String sign(String content, String privateKey) {

54 try {

55 Base64 base64 = new Base64();

56 PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(base64.decode(privateKey));

57 KeyFactory keyf = KeyFactory.getInstance("RSA");

58 PrivateKey priKey = keyf.generatePrivate(priPKCS8);

59 java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

60 signature.initSign(priKey);

61 signature.update(content.getBytes());

62 byte[] signed = signature.sign();

63 return new String(base64.encode(signed));

64 } catch (Exception e) {

65 e.printStackTrace();

66 }

67 return null;

68 }

69

70 /**

71 * RSA验签名检查

72 *

73 * @param content

74 * 待签名数据

75 * @param sign

76 * 签名值

77 * @param publicKey

78 * 分配给开发商公钥

79 * @param encode

80 * 字符集编码

81 * @return 布尔值

82 */

83 public static boolean doCheck(String content, String sign, String publicKey, String encode) {

84 try {

85 KeyFactory keyFactory = KeyFactory.getInstance("RSA");

86 Base64 base64 = new Base64();

87 byte[] encodedKey = base64.decode(publicKey);

88 PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

89

90 java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

91

92 signature.initVerify(pubKey);

93 signature.update(content.getBytes(encode));

94

95 boolean bverify = signature.verify(base64.decode(sign));

96 return bverify;

97

98 } catch (Exception e) {

99 e.printStackTrace();

100 }

101

102 return false;

103 }

104

105 public static boolean doCheck(String content, String sign, String publicKey) {

106 try {

107 KeyFactory keyFactory = KeyFactory.getInstance("RSA");

108 Base64 base64 = new Base64();

109 byte[] encodedKey = base64.decode(publicKey);

110 PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

111

112 java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

113

114 signature.initVerify(pubKey);

115 signature.update(content.getBytes());

116

117 boolean bverify = signature.verify(base64.decode(sign));

118 return bverify;

119

120 } catch (Exception e) {

121 e.printStackTrace();

122 }

123

124 return false;

125 }

126

127 }

48304ba5e6f9fe08f3fa1abda7d326ab.png

最后是一个MainTest:

48304ba5e6f9fe08f3fa1abda7d326ab.png

1 import org.apache.commons.codec.binary.Base64;

2

3 public class MainTest {

4

5 public static void main(String[] args) throws Exception {

6 String filepath = "G:/tmp/";

7

8 // RSAEncrypt.genKeyPair(filepath);

9

10 Base64 base64 = new Base64();

11

12 System.out.println("--------------公钥加密私钥解密过程-------------------");

13 String plainText = "ihep_公钥加密私钥解密";

14 // 公钥加密过程

15 byte[] cipherData = RSAEncrypt.encrypt(RSAEncrypt.loadPublicKeyByStr(RSAEncrypt.loadPublicKeyByFile(filepath)),

16 plainText.getBytes());

17 String cipher = new String(base64.encode(cipherData));

18 // 私钥解密过程

19 byte[] res = RSAEncrypt.decrypt(RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadPrivateKeyByFile(filepath)),

20 base64.decode(cipher));

21 String restr = new String(res);

22 System.out.println("原文:" + plainText);

23 System.out.println("加密:" + cipher);

24 System.out.println("解密:" + restr);

25 System.out.println();

26

27 System.out.println("--------------私钥加密公钥解密过程-------------------");

28 plainText = "ihep_私钥加密公钥解密";

29 // 私钥加密过程

30 cipherData = RSAEncrypt.encrypt(RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadPrivateKeyByFile(filepath)),

31 plainText.getBytes());

32 cipher = new String(base64.encode(cipherData));

33 // 公钥解密过程

34 res = RSAEncrypt.decrypt(RSAEncrypt.loadPublicKeyByStr(RSAEncrypt.loadPublicKeyByFile(filepath)),

35 base64.decode(cipher));

36 restr = new String(res);

37 System.out.println("原文:" + plainText);

38 System.out.println("加密:" + cipher);

39 System.out.println("解密:" + restr);

40 System.out.println();

41

42 System.out.println("---------------私钥签名过程------------------");

43 String content = "ihep_这是用于签名的原始数据";

44 String signstr = RSASignature.sign(content, RSAEncrypt.loadPrivateKeyByFile(filepath));

45 System.out.println("签名原串:" + content);

46 System.out.println("签名串:" + signstr);

47 System.out.println();

48

49 System.out.println("---------------公钥校验签名------------------");

50 System.out.println("签名原串:" + content);

51 System.out.println("签名串:" + signstr);

52

53 System.out.println("验签结果:" + RSASignature.doCheck(content, signstr, RSAEncrypt.loadPublicKeyByFile(filepath)));

54 System.out.println();

55

56 }

57 }

48304ba5e6f9fe08f3fa1abda7d326ab.png

参考:

http://blog.csdn.net/chaijunkun/article/details/7275632

http://blog.csdn.net/wangqiuyun/article/details/42143957

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值