package com.kengkeng.rsa;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class RSAUtil {
public static void main(String[] args) {
String str = "我们都是共产主义接班人。";
String crypt = encryptByPrivateKey(str);
System.out.println("私钥加密密文:" + crypt);
String result = decryptByPublicKey(crypt);
System.out.println("公钥解密原文:" + result);
System.out.println("---");
str = "我们都是共产主义接班人。";
crypt = encryptByPublicKey(str);
System.out.println("公钥加密密文:" + crypt);
result = decryptByPrivateKey(crypt);
System.out.println("密钥解密原文:" + result);
System.out.println("---");
str = "签名。";
System.out.println("原文:" + str);
String str1 = signByPrivateKey(str);
System.out.println("签名结果:" + str1);
if (verifyByPublicKey(str1, str)) {
System.out.println("成功");
} else {
System.out.println("失败");
}
}
/**
* 密钥
*/
private static String priKey = readStringFromFile("pri.key");
/**
* 公钥
*/
private static String pubKey = readStringFromFile("pub.key");
/**
* 加密算法RSA
*/
public static final String KEY_ALGORITHM = "RSA";
/**
* 签名算法
*/
public static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* 使用私钥加密
* @param data 源数据
* @see decByPriKey
*/
public static String encryptByPrivateKey(String data) {
// 加密
String str = "";
try {
byte[] priByte = base64decode(priKey.trim());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(priByte);
KeyFactory fac = KeyFactory.getInstance(KEY_ALGORITHM);
RSAPrivateKey privateKey = (RSAPrivateKey) fac.generatePrivate(keySpec);
//算法/模式/填充
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
int inputLen = data.getBytes().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.getBytes(), offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data.getBytes(), offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
str = base64encode(encryptedData);
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
/**
* 使用私钥解密
* @param data 已加密数据
* @see decByPriKey
*/
public static String decryptByPrivateKey(String data) {
// 加密
String str = "";
try {
byte[] priByte = base64decode(priKey.trim());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(priByte);
KeyFactory fac = KeyFactory.getInstance(KEY_ALGORITHM);
RSAPrivateKey privateKey = (RSAPrivateKey) fac.generatePrivate(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] dataBytes = Base64.decodeBase64(data);
int inputLen = dataBytes.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(dataBytes, offset, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
// 解密后的内容
str = new String(decryptedData);
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
/**
* 使用公钥加密
* @param data 源数据
* @see decByPriKey
*/
public static String encryptByPublicKey(String data) {
// 加密
String str = "";
try {
byte[] pubByte = base64decode(pubKey.trim());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubByte);
KeyFactory fac = KeyFactory.getInstance(KEY_ALGORITHM);
RSAPublicKey rsaPubKey = (RSAPublicKey) fac.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, rsaPubKey);
int inputLen = data.getBytes().length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
while (inputLen - offSet > 0) {
//MAX_ENCRYPT_BLOCK 117
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data.getBytes(), offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data.getBytes(), offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
str = base64encode(encryptedData);
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
/**
* 使用公钥解密
* @param data 已加密数据
* @see decByPriKey
*/
public static String decryptByPublicKey(String data) {
// 加密
String str = "";
try {
byte[] pubByte = base64decode(pubKey.trim());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubByte);
KeyFactory fac = KeyFactory.getInstance(KEY_ALGORITHM);
RSAPublicKey rsaPubKey = (RSAPublicKey) fac.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, rsaPubKey);
byte[] dataBytes = Base64.decodeBase64(data);
int inputLen = dataBytes.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(dataBytes, offset, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
str = new String(decryptedData);
} catch (Exception e) {
e.printStackTrace();
}
// 解密后的内容
return str;
}
/**
* 本方法使用SHA1withRSA签名算法产生签名
*
* @param String src 签名的原字符串
* @return String 签名的返回结果(16进制编码)。当产生签名出错的时候,返回null。
*/
public static String signByPrivateKey(String src) {
try {
Signature sigEng = Signature.getInstance(SIGNATURE_ALGORITHM);
byte[] priByte = base64decode(priKey.trim());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(priByte);
KeyFactory fac = KeyFactory.getInstance(KEY_ALGORITHM);
RSAPrivateKey privateKey = (RSAPrivateKey) fac.generatePrivate(keySpec);
sigEng.initSign(privateKey);
sigEng.update(src.getBytes());
byte[] signature = sigEng.sign();
return base64encode(signature);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 使用共钥验证签名
*
* @param sign
* @param src
* @return
*/
public static boolean verifyByPublicKey(String sign, String src) {
try {
Signature sigEng = Signature.getInstance(SIGNATURE_ALGORITHM);
byte[] pubByte = base64decode(pubKey.trim());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubByte);
KeyFactory fac = KeyFactory.getInstance(KEY_ALGORITHM);
RSAPublicKey rsaPubKey = (RSAPublicKey) fac.generatePublic(keySpec);
sigEng.initVerify(rsaPubKey);
sigEng.update(src.getBytes());
byte[] sign1 = base64decode(sign);
return sigEng.verify(sign1);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* base64加密
*
* @param bytes
* @return
*/
@SuppressWarnings("restriction")
private static String base64encode(byte[] bytes) {
String str = new sun.misc.BASE64Encoder().encode(bytes);
str = str.replaceAll("\r\n", "").replaceAll("\r", "").replaceAll("\n", "");
return str;
}
/**
* base64解密
*
* @param str
* @return byte[]
*/
@SuppressWarnings("restriction")
private static byte[] base64decode(String str) {
byte[] bt = null;
try {
sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
bt = decoder.decodeBuffer(str);
} catch (IOException e) {
e.printStackTrace();
}
return bt;
}
/**
* 从文件中读取所有字符串
*
* @param fileName
* @return String
*/
private static String readStringFromFile(String fileName) {
StringBuffer str = new StringBuffer();
try {
File file = new File(fileName);
FileReader fr = new FileReader(file);
char[] temp = new char[1024];
while (fr.read(temp) != -1) {
str.append(temp);
}
fr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return str.toString();
}
}