该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1.jar
注意:
RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行。
RSA加密对明文的长度是有限制的,如果加密数据过大会抛出如下异常:

Exception
in
thread
"main" javax.crypto.IllegalBlockSizeExceptio
n:
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
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;
public class RSAUtils
{
public static final String
KEY_ALGORITHM
=
"RSA";
public static final String
SIGNATURE_ALGORITHM
=
"MD5withRSA";
private static final String
PUBLIC_KEY
=
"RSAPublicKey";
private static final String
PRIVATE_KEY
=
"RSAPrivateKey";
private static final int MAX_ENCRYPT_BLOCK
=
117;
private static final int MAX_DECRYPT_BLOCK
=
128;
public static Map
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
keyMap
=
new HashMap(2);
keyMap.put(PUBLIC_KEY,
publicKey);
keyMap.put(PRIVATE_KEY,
privateKey);
return keyMap;
}
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());
}
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));
}
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;
}
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;
}
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;
}
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;
}
public static String
getPrivateKey(Map
keyMap)
throws Exception
{
Key
key
=
(Key)
keyMap.get(PRIVATE_KEY);
return Base64Utils.encode(key.getEncoded());
}
public static String
getPublicKey(Map
keyMap)
throws Exception
{
Key
key
=
(Key)
keyMap.get(PUBLIC_KEY);
return Base64Utils.encode(key.getEncoded());
}

}

Base64Utils.java
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;
public class Base64Utils
{
private static final int CACHE_SIZE
=
1024;
public static byte[]
decode(String base64)
throws Exception
{
return Base64.decode(base64.getBytes());
}
public static String
encode(
byte[]
bytes)
throws Exception
{
return new String(Base64.encode(bytes));
}
public static String
encodeFile(String filePath)
throws Exception
{
byte[]
bytes
=
fileToByte(filePath);
return encode(bytes);
}
public static void decodeToFile(String
filePath, String base64)
throws Exception
{
byte[]
bytes
=
decode(base64);
byteArrayToFile(bytes, filePath);
}
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;
}
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
package security;
import java.util.Map;
public class RSATester
{
static String
publicKey;
static String
privateKey;
static {
try {
Map
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);
}

}