Java RSA 加密 解密 签名 验签

本文详细介绍了非对称加密的基本概念及其应用场景,并重点解析了RSA加密算法的工作原理及其实现过程。通过示例代码展示了如何生成RSA密钥对、进行数据加密解密以及数字签名验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[b]1. 加密的作用[/b]

1)明文变密文(你不知道密钥是很难解密的);
2)数据的一致性(hash值一样);
3)数据的可信任性(验签)。

[b]2. 两种不同的加密与解密[/b]

[b]1)对称加密[/b]:加密与解密使用相同的密钥,处理速度快;
[b]2)非对称加密[/b]:加密与解密使用不同的密钥(生对生成),处理速度不及对称加密。

[b]3.在非对称加密中,究竟是公钥加密还是私钥加密的问题[/b]

[b]1)如果只是用加密的用途[/b]
公钥加密,私钥解密(私钥只有一个,公钥大家都知道)。
[b]2)如果用验签[/b]
私钥加密,公钥解密(解密的来源是私钥,其它的来源是不可信任的)。

下面是两个工具类。

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;

public class RSAHelper {
public static final String KEY_ALGORITHM = "RSA";
private static final int KEY_LENGTH = 1024;
public static final String PUBLIC_KEY = "PublicKey";
public static final String PRIVATE_KEY = "PrivateKey";
private static final int MAX_ENCRYPT_BLOCK = 117;
private static final int MAX_DECRYPT_BLOCK = 128;
private static final String SIGNATURE_ALGORITHM = "MD5withRSA";

public RSAHelper() {
}

public static void generateKeyPair(Map<String, Object> keyMap) {
boolean result = false;

KeyPairGenerator keyPairGenerator = null;
try {
keyPairGenerator = KeyPairGenerator.getInstance("RSA");
result = true;
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,
ex);
}

if (result) {
SecureRandom secureRandom = new SecureRandom();

String currentDateTime = new SimpleDateFormat("yyyyMMddHHmmssSSS")
.format(new Date());
secureRandom.setSeed(currentDateTime.getBytes());

keyPairGenerator.initialize(1024, secureRandom);

KeyPair keyPair = keyPairGenerator.genKeyPair();

PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();

keyMap.put("PublicKey", publicKey.getEncoded());
keyMap.put("PrivateKey", privateKey.getEncoded());
}
}

public static void saveKeyPair(Map<String, Object> keyPair,
String publicKeyFileName, String privateKeyFileName) {
try {
FileOutputStream fileOutputStream = new FileOutputStream(
publicKeyFileName);
byte[] publicKey = (byte[]) keyPair.get("PublicKey");
fileOutputStream.write(publicKey);
fileOutputStream.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,
ex);
} catch (IOException ex) {
Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,
ex);
}

try {
FileOutputStream fileOutputStream = new FileOutputStream(
privateKeyFileName);
byte[] privateKey = (byte[]) keyPair.get("PrivateKey");
fileOutputStream.write(privateKey);
fileOutputStream.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,
ex);
} catch (IOException ex) {
Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,
ex);
}
}

public static byte[] getKey(String keyFileName) {
byte[] keyBytes = null;
try {
File file = new File(keyFileName);
FileInputStream fileInputStream = new FileInputStream(file);
DataInputStream dataInputStream = new DataInputStream(
fileInputStream);

keyBytes = new byte[(int) file.length()];

dataInputStream.readFully(keyBytes);

dataInputStream.close();
fileInputStream.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,
ex);
} catch (IOException ex) {
Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,
ex);
}

return keyBytes;
}

public static byte[] encryptWithPublicKey(byte[] data, int offSet,
int length, byte[] keyBytes) throws Exception {
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key publicK = keyFactory.generatePublic(x509KeySpec);

Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(1, publicK);
ByteArrayOutputStream out = new ByteArrayOutputStream();

int i = 0;

while (length - offSet > 0) {
byte[] cache;
if (length - offSet > 117) {
cache = cipher.doFinal(data, offSet, 117);
} else {
cache = cipher.doFinal(data, offSet, length - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * 117;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}

public static byte[] encryptWithPrivateKey(byte[] data, int offSet,
int length, byte[] keyBytes) throws Exception {
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(1, privateK);
ByteArrayOutputStream out = new ByteArrayOutputStream();

int i = 0;

while (length - offSet > 0) {
byte[] cache;
if (length - offSet > 117) {
cache = cipher.doFinal(data, offSet, 117);
} else {
cache = cipher.doFinal(data, offSet, length - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * 117;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}

public static byte[] decryptWithPublicKey(byte[] data, int offSet,
int length, byte[] keyBytes) throws Exception {
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(2, publicK);
ByteArrayOutputStream out = new ByteArrayOutputStream();

int i = 0;

while (length - offSet > 0) {
byte[] cache;
if (length - offSet > 128) {
cache = cipher.doFinal(data, offSet, 128);
} else {
cache = cipher.doFinal(data, offSet, length - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * 128;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}

public static byte[] decryptWithPrivateKey(byte[] data, int offSet,
int length, byte[] keyBytes) throws Exception {
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(2, privateK);
ByteArrayOutputStream out = new ByteArrayOutputStream();

int i = 0;

while (length - offSet > 0) {
byte[] cache;
if (length - offSet > 128) {
cache = cipher.doFinal(data, offSet, 128);
} else {
cache = cipher.doFinal(data, offSet, length - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * 128;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}

public static byte[] sign(byte[] data, int offset, int length,
byte[] privateKeyBytes) {
byte[] signedData = null;
try {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
privateKeyBytes);

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

PrivateKey privateKey = keyFactory
.generatePrivate(pkcs8EncodedKeySpec);

Signature signature = Signature.getInstance("MD5withRSA");

signature.initSign(privateKey);

signature.update(data, offset, length);

signedData = signature.sign();
} catch (Exception ex) {
Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,
ex);
}

return signedData;
}

public static boolean verify(byte[] data, int offset, int length,
byte[] publicKeyBytes, byte[] dataSignature) {
boolean result = false;
try {
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
publicKeyBytes);

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

PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

Signature signature = Signature.getInstance("MD5withRSA");

signature.initVerify(publicKey);

signature.update(data, offset, length);

result = signature.verify(dataSignature);
} catch (Exception ex) {
Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,
ex);
}

return result;
}
}



import com.adph.jms.Base64Utils;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;

public class RSAKeyUtils {
private static String RAS_PUBLICKEY_PATH = "D://security.key";
private static String RSA_PRIVATEKEY_PATH= "D://security.crt";

public RSAKeyUtils() {
}

protected static void init(String RAS_PUBLICKEY_PATH,
String RSA_PRIVATEKEY_PATH) {
try {
FileUtils.forceMkdir(new File(new File(RAS_PUBLICKEY_PATH)
.getParent()));
Map<String, Object> keyPair = new HashMap();
RSAHelper.generateKeyPair(keyPair);
RSAHelper.saveKeyPair(keyPair, RAS_PUBLICKEY_PATH,
RSA_PRIVATEKEY_PATH);
} catch (IOException e) {
e.printStackTrace();
}
}

public static void setKeyPath(String keyPath) {
RAS_PUBLICKEY_PATH = keyPath;
}

public static void setCrtPath(String crtPath) {
RSA_PRIVATEKEY_PATH = crtPath;
}

public static String encByPublicKey(String data) {
String dataBack = "";
try {
if (!StringUtils.isEmpty(data)) {
byte[] Bytes = RSAHelper.encryptWithPublicKey(data.getBytes(),
0, data.getBytes().length,
RSAHelper.getKey(RAS_PUBLICKEY_PATH));
dataBack = Base64Utils.encode(Bytes);
}
} catch (Exception e) {
e.printStackTrace();
}
return dataBack;
}

public static String encByPrivateKey(String data) {
String dataBack = "";
try {
if (!StringUtils.isEmpty(data)) {
byte[] Bytes = RSAHelper.encryptWithPrivateKey(data.getBytes(),
0, data.getBytes().length,
RSAHelper.getKey(RSA_PRIVATEKEY_PATH));
dataBack = Base64Utils.encode(Bytes);
}
} catch (Exception e) {
e.printStackTrace();
}
return dataBack;
}

public static String decByPublicKey(String data) {
String dataBack = "";
try {
if (!StringUtils.isEmpty(data)) {
byte[] Bytes = RSAHelper.decryptWithPublicKey(
Base64Utils.decode(data), 0,
Base64Utils.decode(data).length,
RSAHelper.getKey(RAS_PUBLICKEY_PATH));
dataBack = new String(Bytes);
}
} catch (Exception e) {
e.printStackTrace();
}
return dataBack;
}

public static String decByPrivateKey(String data) {
String dataBack = "";
try {
if (!StringUtils.isEmpty(data)) {
byte[] Bytes = RSAHelper.decryptWithPrivateKey(
Base64Utils.decode(data), 0,
Base64Utils.decode(data).length,
RSAHelper.getKey(RSA_PRIVATEKEY_PATH));
dataBack = new String(Bytes);
}
} catch (Exception e) {
e.printStackTrace();
}
return dataBack;
}

public static String doSignPrivateKey(String data) {
String dataBack = "";
try {
if (!StringUtils.isEmpty(data)) {
byte[] Bytes = RSAHelper.sign(data.getBytes(), 0,
data.getBytes().length,
RSAHelper.getKey(RSA_PRIVATEKEY_PATH));
dataBack = Base64Utils.encode(Bytes);
}
} catch (Exception e) {
e.printStackTrace();
}
return dataBack;
}

public static boolean doVerifyPublicKey(String data, String sign) {
Boolean returnFlag = Boolean.FALSE;
if ((StringUtils.isEmpty(data)) || (StringUtils.isEmpty(sign))) {
return Boolean.FALSE.booleanValue();
}
try {
returnFlag = Boolean.valueOf(RSAHelper.verify(data.getBytes(), 0,
data.getBytes().length,
RSAHelper.getKey(RAS_PUBLICKEY_PATH),
Base64Utils.decode(sign)));
} catch (Exception e) {
e.printStackTrace();
}
return returnFlag.booleanValue();
}

// public static void main(String[] args) {
// init("D://security.key", "D://security.crt");
// }
}


写一个例子测试下。[b]注意:先要运行上面main方法,使其生成security.key和security.crt。[/b]


public class EncTest {
public static void main(String[] args) throws Exception {
String text = "Hello World";
String enc = RSAKeyUtils.encByPublicKey(text);
System.out.println("加密数据:" + enc);
System.out.println("解密数据:" + RSAKeyUtils.decByPrivateKey(enc));
String sign=RSAKeyUtils.doSignPrivateKey(text);
System.out.println("签名:"+sign);
System.out.println("验签结果:"+RSAKeyUtils.doVerifyPublicKey(text, sign));
}
}
1、数字签名原理 用RSA算法做数字签名,总的来说,就是签名者用私钥参数d加密,也就是签名证者用字者的公钥参数e解密来完成认证。 下面简要描述数字签名和认证的过程。 (1)、生成密钥 为用户随机生成一对密钥:公钥(e,n)和私钥(d,n). (2)、签名过程 a) 计算消息的散列值H(M). b) 用私钥(d,n)加密散列值:s=(H(M)) mod n,签名结果就是s. c) 发送消息和签名(M,s). (3)、认证过程 a) 取得发送方的公钥(e,n). b) 解密签名s:h=s mod n. c) 计算消息的散列值H(M). d) 比较,如果h=H(M),表示签名有效;否则,签名无效。 根据上面的过程,我们可以得到RSA数字签名的框图如图2-1: 图 2-1 RSA数字签名框图 2、 假设Alice想和Bob通信,以本地两个文件夹Alice和Bob模拟两个用户,实现消息M和签名的模拟分发 (1)、Alice通过RSA算法生成一对密钥:公钥(e,n)和私钥(d,n),将公私钥分别存入pubKey.txt和priKey.txt中。 pubKey.txt中公钥如下: priKey.txt中私钥如下: (2)、将Alice中的pubKey.txt拷到Bob中,模拟公玥的分发。 (3)、将Alice中的消息info.txt做散列,将散列后的值存入hashInfo.txt中。 (4)、将Alice中的消息hashInfo.txt和签名sign.txt拷到Bob中,实现M密文状态下的签名与模拟分发、消息传递。 (5)Bob取得公钥pubKey.txt,用公钥解密签名,计算消息的散列值H(M).比较,如果h=H(M),表示签名有效;否则,签名无效。 后台运行结果如下:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值