Java RSA加密解密实现方法分析【附BASE64 jar包下载】

2025-05-29 0 67

本文实例讲述了Java RSA加密解密实现方法。分享给大家供大家参考,具体如下:

该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1.jar

javabase64-1.3.1.jar 本站下载地址

注意:

RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行。

RSA加密对明文的长度是有限制的,如果加密数据过大会抛出如下异常:

?

1

2

3

4
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes

at com.sun.crypto.provider.RSACipher.a(DashoA13*..)

at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)

at javax.crypto.Cipher.doFinal(DashoA13*..)

RSAUtils.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

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

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304
package security;

import java.io.ByteArrayOutputStream;

import java.security.Key;

import java.security.KeyFactory;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.PrivateKey;

import java.security.PublicKey;

import java.security.Signature;

import java.security.interfaces.RSAPrivateKey;

import java.security.interfaces.RSAPublicKey;

import java.security.spec.PKCS8EncodedKeySpec;

import java.security.spec.X509EncodedKeySpec;

import java.util.HashMap;

import java.util.Map;

import javax.crypto.Cipher;

/** *//**

* <p>

* RSA公钥/私钥/签名工具包

* </p>

* <p>

* 罗纳德·李维斯特(Ron [R]ivest)、阿迪·萨莫尔(Adi [S]hamir)和伦纳德·阿德曼(Leonard [A]dleman)

* </p>

* <p>

* 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>

* 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>

* 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全

* </p>

*

* @author IceWee

* @date 2012-4-26

* @version 1.0

*/

public class RSAUtils {

/** *//**

* 加密算法RSA

*/

public static final String KEY_ALGORITHM = "RSA";

/** *//**

* 签名算法

*/

public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

/** *//**

* 获取公钥的key

*/

private static final String PUBLIC_KEY = "RSAPublicKey";

/** *//**

* 获取私钥的key

*/

private static final String PRIVATE_KEY = "RSAPrivateKey";

/** *//**

* RSA最大加密明文大小

*/

private static final int MAX_ENCRYPT_BLOCK = 117;

/** *//**

* RSA最大解密密文大小

*/

private static final int MAX_DECRYPT_BLOCK = 128;

/** *//**

* <p>

* 生成密钥对(公钥和私钥)

* </p>

*

* @return

* @throws Exception

*/

public static Map<String, Object> genKeyPair() throws Exception {

KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);

keyPairGen.initialize(1024);

KeyPair keyPair = keyPairGen.generateKeyPair();

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

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

Map<String, Object> keyMap = new HashMap<String, Object>(2);

keyMap.put(PUBLIC_KEY, publicKey);

keyMap.put(PRIVATE_KEY, privateKey);

return keyMap;

}

/** *//**

* <p>

* 用私钥对信息生成数字签名

* </p>

*

* @param data 已加密数据

* @param privateKey 私钥(BASE64编码)

*

* @return

* @throws Exception

*/

public static String sign(byte[] data, String privateKey) throws Exception {

byte[] keyBytes = Base64Utils.decode(privateKey);

PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);

Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);

signature.initSign(privateK);

signature.update(data);

return Base64Utils.encode(signature.sign());

}

/** *//**

* <p>

* 校验数字签名

* </p>

*

* @param data 已加密数据

* @param publicKey 公钥(BASE64编码)

* @param sign 数字签名

*

* @return

* @throws Exception

*

*/

public static boolean verify(byte[] data, String publicKey, String sign)

throws Exception {

byte[] keyBytes = Base64Utils.decode(publicKey);

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

PublicKey publicK = keyFactory.generatePublic(keySpec);

Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);

signature.initVerify(publicK);

signature.update(data);

return signature.verify(Base64Utils.decode(sign));

}

/** *//**

* <P>

* 私钥解密

* </p>

*

* @param encryptedData 已加密数据

* @param privateKey 私钥(BASE64编码)

* @return

* @throws Exception

*/

public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)

throws Exception {

byte[] keyBytes = Base64Utils.decode(privateKey);

PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);

Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.DECRYPT_MODE, privateK);

int inputLen = encryptedData.length;

ByteArrayOutputStream out = new ByteArrayOutputStream();

int offSet = 0;

byte[] cache;

int i = 0;

// 对数据分段解密

while (inputLen - offSet > 0) {

if (inputLen - offSet > MAX_DECRYPT_BLOCK) {

cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);

} else {

cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);

}

out.write(cache, 0, cache.length);

i++;

offSet = i * MAX_DECRYPT_BLOCK;

}

byte[] decryptedData = out.toByteArray();

out.close();

return decryptedData;

}

/** *//**

* <p>

* 公钥解密

* </p>

*

* @param encryptedData 已加密数据

* @param publicKey 公钥(BASE64编码)

* @return

* @throws Exception

*/

public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)

throws Exception {

byte[] keyBytes = Base64Utils.decode(publicKey);

X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

Key publicK = keyFactory.generatePublic(x509KeySpec);

Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.DECRYPT_MODE, publicK);

int inputLen = encryptedData.length;

ByteArrayOutputStream out = new ByteArrayOutputStream();

int offSet = 0;

byte[] cache;

int i = 0;

// 对数据分段解密

while (inputLen - offSet > 0) {

if (inputLen - offSet > MAX_DECRYPT_BLOCK) {

cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);

} else {

cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);

}

out.write(cache, 0, cache.length);

i++;

offSet = i * MAX_DECRYPT_BLOCK;

}

byte[] decryptedData = out.toByteArray();

out.close();

return decryptedData;

}

/** *//**

* <p>

* 公钥加密

* </p>

*

* @param data 源数据

* @param publicKey 公钥(BASE64编码)

* @return

* @throws Exception

*/

public static byte[] encryptByPublicKey(byte[] data, String publicKey)

throws Exception {

byte[] keyBytes = Base64Utils.decode(publicKey);

X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

Key publicK = keyFactory.generatePublic(x509KeySpec);

// 对数据加密

Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.ENCRYPT_MODE, publicK);

int inputLen = data.length;

ByteArrayOutputStream out = new ByteArrayOutputStream();

int offSet = 0;

byte[] cache;

int i = 0;

// 对数据分段加密

while (inputLen - offSet > 0) {

if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {

cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);

} else {

cache = cipher.doFinal(data, offSet, inputLen - offSet);

}

out.write(cache, 0, cache.length);

i++;

offSet = i * MAX_ENCRYPT_BLOCK;

}

byte[] encryptedData = out.toByteArray();

out.close();

return encryptedData;

}

/** *//**

* <p>

* 私钥加密

* </p>

*

* @param data 源数据

* @param privateKey 私钥(BASE64编码)

* @return

* @throws Exception

*/

public static byte[] encryptByPrivateKey(byte[] data, String privateKey)

throws Exception {

byte[] keyBytes = Base64Utils.decode(privateKey);

PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);

Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.ENCRYPT_MODE, privateK);

int inputLen = data.length;

ByteArrayOutputStream out = new ByteArrayOutputStream();

int offSet = 0;

byte[] cache;

int i = 0;

// 对数据分段加密

while (inputLen - offSet > 0) {

if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {

cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);

} else {

cache = cipher.doFinal(data, offSet, inputLen - offSet);

}

out.write(cache, 0, cache.length);

i++;

offSet = i * MAX_ENCRYPT_BLOCK;

}

byte[] encryptedData = out.toByteArray();

out.close();

return encryptedData;

}

/** *//**

* <p>

* 获取私钥

* </p>

*

* @param keyMap 密钥对

* @return

* @throws Exception

*/

public static String getPrivateKey(Map<String, Object> keyMap)

throws Exception {

Key key = (Key) keyMap.get(PRIVATE_KEY);

return Base64Utils.encode(key.getEncoded());

}

/** *//**

* <p>

* 获取公钥

* </p>

*

* @param keyMap 密钥对

* @return

* @throws Exception

*/

public static String getPublicKey(Map<String, Object> keyMap)

throws Exception {

Key key = (Key) keyMap.get(PUBLIC_KEY);

return Base64Utils.encode(key.getEncoded());

}

}

Base64Utils.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

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
package security;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.io.OutputStream;

import it.sauronsoftware.base64.Base64;

/** *//**

* <p>

* BASE64编码解码工具包

* </p>

* <p>

* 依赖javabase64-1.3.1.jar

* </p>

*

* @author IceWee

* @date 2012-5-19

* @version 1.0

*/

public class Base64Utils {

/** *//**

* 文件读取缓冲区大小

*/

private static final int CACHE_SIZE = 1024;

/** *//**

* <p>

* BASE64字符串解码为二进制数据

* </p>

*

* @param base64

* @return

* @throws Exception

*/

public static byte[] decode(String base64) throws Exception {

return Base64.decode(base64.getBytes());

}

/** *//**

* <p>

* 二进制数据编码为BASE64字符串

* </p>

*

* @param bytes

* @return

* @throws Exception

*/

public static String encode(byte[] bytes) throws Exception {

return new String(Base64.encode(bytes));

}

/** *//**

* <p>

* 将文件编码为BASE64字符串

* </p>

* <p>

* 大文件慎用,可能会导致内存溢出

* </p>

*

* @param filePath 文件绝对路径

* @return

* @throws Exception

*/

public static String encodeFile(String filePath) throws Exception {

byte[] bytes = fileToByte(filePath);

return encode(bytes);

}

/** *//**

* <p>

* BASE64字符串转回文件

* </p>

*

* @param filePath 文件绝对路径

* @param base64 编码字符串

* @throws Exception

*/

public static void decodeToFile(String filePath, String base64) throws Exception {

byte[] bytes = decode(base64);

byteArrayToFile(bytes, filePath);

}

/** *//**

* <p>

* 文件转换为二进制数组

* </p>

*

* @param filePath 文件路径

* @return

* @throws Exception

*/

public static byte[] fileToByte(String filePath) throws Exception {

byte[] data = new byte[0];

File file = new File(filePath);

if (file.exists()) {

FileInputStream in = new FileInputStream(file);

ByteArrayOutputStream out = new ByteArrayOutputStream(2048);

byte[] cache = new byte[CACHE_SIZE];

int nRead = 0;

while ((nRead = in.read(cache)) != -1) {

out.write(cache, 0, nRead);

out.flush();

}

out.close();

in.close();

data = out.toByteArray();

}

return data;

}

/** *//**

* <p>

* 二进制数据写文件

* </p>

*

* @param bytes 二进制数据

* @param filePath 文件生成目录

*/

public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {

InputStream in = new ByteArrayInputStream(bytes);

File destFile = new File(filePath);

if (!destFile.getParentFile().exists()) {

destFile.getParentFile().mkdirs();

}

destFile.createNewFile();

OutputStream out = new FileOutputStream(destFile);

byte[] cache = new byte[CACHE_SIZE];

int nRead = 0;

while ((nRead = in.read(cache)) != -1) {

out.write(cache, 0, nRead);

out.flush();

}

out.close();

in.close();

}

}

RSATester.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
package security;

import java.util.Map;

public class RSATester {

static String publicKey;

static String privateKey;

static {

try {

Map<String, Object> keyMap = RSAUtils.genKeyPair();

publicKey = RSAUtils.getPublicKey(keyMap);

privateKey = RSAUtils.getPrivateKey(keyMap);

System.err.println("公钥: \\n\\r" + publicKey);

System.err.println("私钥: \\n\\r" + privateKey);

} catch (Exception e) {

e.printStackTrace();

}

}

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

test();

testSign();

}

static void test() throws Exception {

System.err.println("公钥加密——私钥解密");

String source = "这是一行没有任何意义的文字,你看完了等于没看,不是吗?";

System.out.println("\\r加密前文字:\\r\\n" + source);

byte[] data = source.getBytes();

byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);

System.out.println("加密后文字:\\r\\n" + new String(encodedData));

byte[] decodedData = RSAUtils.decryptByPrivateKey(encodedData, privateKey);

String target = new String(decodedData);

System.out.println("解密后文字: \\r\\n" + target);

}

static void testSign() throws Exception {

System.err.println("私钥加密——公钥解密");

String source = "这是一行测试RSA数字签名的无意义文字";

System.out.println("原文字:\\r\\n" + source);

byte[] data = source.getBytes();

byte[] encodedData = RSAUtils.encryptByPrivateKey(data, privateKey);

System.out.println("加密后:\\r\\n" + new String(encodedData));

byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, publicKey);

String target = new String(decodedData);

System.out.println("解密后: \\r\\n" + target);

System.err.println("私钥签名——公钥验证签名");

String sign = RSAUtils.sign(encodedData, privateKey);

System.err.println("签名:\\r" + sign);

boolean status = RSAUtils.verify(encodedData, publicKey, sign);

System.err.println("验证结果:\\r" + status);

}

}

希望本文所述对大家java程序设计有所帮助。

原文链接:http://blog.csdn.net/centralperk/article/details/8538697

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 Java RSA加密解密实现方法分析【附BASE64 jar包下载】 https://www.kuaiidc.com/114072.html

相关文章

发表评论
暂无评论