class Base64Encoder extends FilterOutputStream {
private static final char[] chars = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '+', '/'
};
private int charCount;
private int carryOver;
/***
* Constructs a new Base64 encoder that writes output to the given
* OutputStream.
*
* @param out the output stream
*/
public Base64Encoder(OutputStream out) {
super(out);
}
/***
* Writes the given byte to the output stream in an encoded form.
*
* @throws IOException if an I/O error occurs
*/
public void write(int b) throws IOException {
// Take 24-bits from three octets, translate into four encoded chars
// Break lines at 76 chars
// If necessary, pad with 0 bits on the right at the end
// Use = signs as padding at the end to ensure encodedLength % 4 == 0
// Remove the sign bit,
// thanks to Christian Schweingruber
if (b < 0) {
b += 256;
}
// First byte use first six bits, save last two bits
if (charCount % 3 == 0) {
int lookup = b >> 2;
carryOver = b & 3; // last two bits
out.write(chars[lookup]);
}
// Second byte use previous two bits and first four new bits,
// save last four bits
else if (charCount % 3 == 1) {
int lookup = ((carryOver << 4) + (b >> 4)) & 63;
carryOver = b & 15; // last four bits
out.write(chars[lookup]);
}
// Third byte use previous four bits and first two new bits,
// then use last six new bits
else if (charCount % 3 == 2) {
int lookup = ((carryOver << 2) + (b >> 6)) & 63;
out.write(chars[lookup]);
lookup = b & 63; // last six bits
out.write(chars[lookup]);
carryOver = 0;
}
charCount++;
// Add newline every 76 output chars (that's 57 input chars)
if (charCount % 57 == 0) {
out.write('\n');
}
}
/***
* Writes the given byte array to the output stream in an
* encoded form.
*
* @param buf the data to be written
* @param off the start offset of the data
* @param len the length of the data
* @throws IOException if an I/O error occurs
*/
public void write(byte[] buf, int off, int len) throws IOException {
// This could of course be optimized
for (int i = 0; i < len; i++) {
write(buf[off + i]);
}
}
/***
* Closes the stream, this MUST be called to ensure proper padding is
* written to the end of the output stream.
*
* @throws IOException if an I/O error occurs
*/
public void close() throws IOException {
// Handle leftover bytes
if (charCount % 3 == 1) { // one leftover
int lookup = (carryOver << 4) & 63;
out.write(chars[lookup]);
out.write('=');
out.write('=');
} else if (charCount % 3 == 2) { // two leftovers
int lookup = (carryOver << 2) & 63;
out.write(chars[lookup]);
out.write('=');
}
super.close();
}
/***
* Returns the encoded form of the given unencoded string. The encoder
* uses the ISO-8859-1 (Latin-1) encoding to convert the string to bytes.
* For greater control over the encoding, encode the string to bytes
* yourself and use encode(byte[]).
*
* @param unencoded the string to encode
* @return the encoded form of the unencoded string
*/
public static String encode(String unencoded) {
byte[] bytes = null;
try {
bytes = unencoded.getBytes("UTF-8");
} catch (UnsupportedEncodingException ignored) {
}
return encode(bytes);
}
/***
* Returns the encoded form of the given unencoded string.
*
* @param bytes the bytes to encode
* @return the encoded form of the unencoded string
*/
public static String encode(byte[] bytes) {
ByteArrayOutputStream out =
new ByteArrayOutputStream((int) (bytes.length * 1.37));
Base64Encoder encodedOut = new Base64Encoder(out);
try {
encodedOut.write(bytes);
encodedOut.close();
return out.toString("UTF-8");
} catch (IOException ignored) {
return null;
}
}
}
class Base64Decoder extends FilterInputStream {
private static final char[] chars = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '+', '/'
};
// A mapping between char values and six-bit integers
private static final int[] ints = new int[128];
static {
for (int i = 0; i < 64; i++) {
ints[chars[i]] = i;
}
}
private int charCount;
private int carryOver;
/***
* Constructs a new Base64 decoder that reads input from the given
* InputStream.
*
* @param in the input stream
*/
public Base64Decoder(InputStream in) {
super(in);
}
/***
* Returns the next decoded character from the stream, or -1 if
* end of stream was reached.
*
* @return the decoded character, or -1 if the end of the
* input stream is reached
* @throws IOException if an I/O error occurs
*/
public int read() throws IOException {
// Read the next non-whitespace character
int x;
do {
x = in.read();
if (x == -1) {
return -1;
}
} while (Character.isWhitespace((char) x));
charCount++;
// The '=' sign is just padding
if (x == '=') {
return -1; // effective end of stream
}
// Convert from raw form to 6-bit form
x = ints[x];
// Calculate which character we're decoding now
int mode = (charCount - 1) % 4;
// First char save all six bits, go for another
if (mode == 0) {
carryOver = x & 63;
return read();
}
// Second char use previous six bits and first two new bits,
// save last four bits
else if (mode == 1) {
int decoded = ((carryOver << 2) + (x >> 4)) & 255;
carryOver = x & 15;
return decoded;
}
// Third char use previous four bits and first four new bits,
// save last two bits
else if (mode == 2) {
int decoded = ((carryOver << 4) + (x >> 2)) & 255;
carryOver = x & 3;
return decoded;
}
// Fourth char use previous two bits and all six new bits
else if (mode == 3) {
int decoded = ((carryOver << 6) + x) & 255;
return decoded;
}
return -1; // can't actually reach this line
}
/***
* Reads decoded data into an array of bytes and returns the actual
* number of bytes read, or -1 if end of stream was reached.
*
* @param buf the buffer into which the data is read
* @param off the start offset of the data
* @param len the maximum number of bytes to read
* @return the actual number of bytes read, or -1 if the end of the
* input stream is reached
* @throws IOException if an I/O error occurs
*/
public int read(byte[] buf, int off, int len) throws IOException {
if (buf.length < (len + off - 1)) {
throw new IOException("The input buffer is too small: " + len +
" bytes requested starting at offset " + off + " while the buffer " +
" is only " + buf.length + " bytes long.");
}
// This could of course be optimized
int i;
for (i = 0; i < len; i++) {
int x = read();
if (x == -1 && i == 0) { // an immediate -1 returns -1
return -1;
} else if (x == -1) { // a later -1 returns the chars read so far
break;
}
buf[off + i] = (byte) x;
}
return i;
}
/***
* Returns the decoded form of the given encoded string, as a String.
* Note that not all binary data can be represented as a String, so this
* method should only be used for encoded String data. Use decodeToBytes()
* otherwise.
*
* @param encoded the string to decode
* @return the decoded form of the encoded string
*/
public static String decode(String encoded) {
return new String(decodeToBytes(encoded));
}
/***
* Returns the decoded form of the given encoded string, as bytes.
*
* @param encoded the string to decode
* @return the decoded form of the encoded string
*/
public static byte[] decodeToBytes(String encoded) {
byte[] bytes = null;
try {
bytes = encoded.getBytes("UTF-8");
} catch (UnsupportedEncodingException ignored) {
}
Base64Decoder in = new Base64Decoder(
new ByteArrayInputStream(bytes));
ByteArrayOutputStream out =
new ByteArrayOutputStream((int) (bytes.length * 0.67));
try {
byte[] buf = new byte[4 * 1024]; // 4K buffer
int bytesRead;
while ((bytesRead = in.read(buf)) != -1) {
out.write(buf, 0, bytesRead);
}
out.close();
return out.toByteArray();
} catch (IOException ignored) {
return null;
}
}
}
package com.example;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* http://www.cnblogs.com/whoislcj/p/5473030.html
*
* 什么是aes加密?
* 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。
*
*/
public class AESUtils {
private final static String HEX = "0123456789ABCDEF";
private static final String CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding";//AES是加密方式 CBC是工作模式 PKCS5Padding是填充模式
private static final String AES = "AES";//AES 加密
private static final String SHA1PRNG = "SHA1PRNG";//// SHA1PRNG 强随机种子算法, 要区别4.2以上版本的调用方法
/*
* 生成随机数,可以当做动态的密钥 加密和解密的密钥必须一致,不然将不能解密
*/
public static String generateKey() {
try {
SecureRandom localSecureRandom = SecureRandom.getInstance(SHA1PRNG);
byte[] bytes_key = new byte[20];
localSecureRandom.nextBytes(bytes_key);
String str_key = toHex(bytes_key);
return str_key;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 对密钥进行处理
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance(AES);
//for android
SecureRandom sr = null;
// 在4.2以上版本中,SecureRandom获取方式发生了改变
// if (android.os.Build.VERSION.SDK_INT >= 17) {
// sr = SecureRandom.getInstance(SHA1PRNG, "Crypto");
// } else {
// sr = SecureRandom.getInstance(SHA1PRNG);
// }
// for Java
sr = SecureRandom.getInstance(SHA1PRNG);
sr.setSeed(seed);
kgen.init(128, sr); //256 bits or 128 bits,192bits
//AES中128位密钥版本有10个加密循环,192比特密钥版本有12个加密循环,256比特密钥版本则有14个加密循环。
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
/*
* 加密
*/
public static String encrypt(String key, String cleartext) {
if ("".equals(cleartext)) {
return cleartext;
}
try {
byte[] result = encrypt(key, cleartext.getBytes());
return Base64Encoder.encode(result);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/*
* 加密
*/
private static byte[] encrypt(String key, byte[] clear) throws Exception {
byte[] raw = getRawKey(key.getBytes());
SecretKeySpec skeySpec = new SecretKeySpec(raw, AES);
Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
/*
* 解密
*/
public static String decrypt(String key, String encrypted) {
if ("".equals(encrypted)) {
return encrypted;
}
try {
byte[] enc = Base64Decoder.decodeToBytes(encrypted);
byte[] result = decrypt(key, enc);
return new String(result);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/*
* 解密
*/
private static byte[] decrypt(String key, byte[] encrypted) throws Exception {
byte[] raw = getRawKey(key.getBytes());
SecretKeySpec skeySpec = new SecretKeySpec(raw, AES);
Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
//二进制转字符
public static String toHex(byte[] buf) {
if (buf == null)
return "";
StringBuffer result = new StringBuffer(2 * buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}
public static void main(String[] args) {
String jsonData = "abcdefghijklmnopqrstuvwxyz";
System.out.println("AESUtils jsonData ---->" + jsonData);
System.out.println("AESUtils jsonData length ---->" + jsonData.length());
//生成key
String secretKey = AESUtils.generateKey();
System.out.println("AESUtils secretKey ---->" + secretKey);
//AES加密
long start = System.currentTimeMillis();
String encryStr = AESUtils.encrypt(secretKey, jsonData);
long end = System.currentTimeMillis();
System.out.println("AESUtils encrypt cost time---->" + (end - start));
System.out.println("AESUtils jsonData(encrypted) ---->" + encryStr);
System.out.println("AESUtils jsonData(encrypted) length ---->" + encryStr.length());
//AES解密
start = System.currentTimeMillis();
String decryStr = AESUtils.decrypt(secretKey, encryStr);
end = System.currentTimeMillis();
System.out.println("AESUtils decrypt cost time---->" + (end - start));
System.out.println("AESUtils jsonData(decrypted) ---->" + decryStr);
}
}
运行结果
AESUtils jsonData ---->abcdefghijklmnopqrstuvwxyz
AESUtils jsonData length ---->26
AESUtils secretKey ---->90588CB299AEDF3F93CA6E023D5548C7B14F0028
AESUtils encrypt cost time---->235
AESUtils jsonData(encrypted) ---->CxX5KAOTuALTw+GvN3lWEu047ST5703NrlYYuofWV4A=
AESUtils jsonData(encrypted) length ---->44
AESUtils decrypt cost time---->0
AESUtils jsonData(decrypted) ---->abcdefghijklmnopqrstuvwxyz
package com.example;
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.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.List;
import javax.crypto.Cipher;
/**
* http://www.cnblogs.com/whoislcj/p/5470095.html
*
*
* RSA算法是最流行的公钥密码算法,使用长度可以变化的密钥。RSA是第一个既能用于数据加密也能用于数字签名的算法。
*
* RSA算法原理如下:
*
* 1.随机选择两个大质数p和q,p不等于q,计算N=pq;
* 2.选择一个大于1小于N的自然数e,e必须与(p-1)(q-1)互素。
* 3.用公式计算出d:d×e = 1 (mod (p-1)(q-1)) 。
* 4.销毁p和q。
*
* 最终得到的N和e就是“公钥”,d就是“私钥”,发送方使用N去加密数据,接收方只有使用d才能解开数据内容。
*
* RSA的安全性依赖于大数分解,小于1024位的N已经被证明是不安全的,而且由于RSA算法进行的都是大数计算,使得RSA最快的情况也比DES慢上倍,这是RSA最大的缺陷,因此通常只能用于加密少量数据或者加密密钥,但RSA仍然不失为一种高强度的算法。
*
*/
public class RSAUtils {
public static final String RSA = "RSA";// 非对称加密密钥算法
public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";//加密填充方式
public static final int DEFAULT_KEY_SIZE = 2048;//秘钥默认长度
public static final byte[] DEFAULT_SPLIT = "#PART#".getBytes(); // 当要加密的内容超过bufferSize,则采用partSplit进行分块加密
public static final int DEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE / 8) - 11;// 当前秘钥支持加密的最大字节数
/**
* 随机生成RSA密钥对
*
* @param keyLength 密钥长度,范围:512~2048
* 一般1024
* @return
*/
public static KeyPair generateRSAKeyPair(int keyLength) {
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
kpg.initialize(keyLength);
return kpg.genKeyPair();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
/**
* 用公钥对字符串进行加密
*
* @param data 原文
*/
public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
// 得到公钥
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
KeyFactory kf = KeyFactory.getInstance(RSA);
PublicKey keyPublic = kf.generatePublic(keySpec);
// 加密数据
Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
cp.init(Cipher.ENCRYPT_MODE, keyPublic);
return cp.doFinal(data);
}
/**
* 私钥加密
*
* @param data 待加密数据
* @param privateKey 密钥
* @return byte[] 加密数据
*/
public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
// 得到私钥
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory kf = KeyFactory.getInstance(RSA);
PrivateKey keyPrivate = kf.generatePrivate(keySpec);
// 数据加密
Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, keyPrivate);
return cipher.doFinal(data);
}
/**
* 公钥解密
*
* @param data 待解密数据
* @param publicKey 密钥
* @return byte[] 解密数据
*/
public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
// 得到公钥
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
KeyFactory kf = KeyFactory.getInstance(RSA);
PublicKey keyPublic = kf.generatePublic(keySpec);
// 数据解密
Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
cipher.init(Cipher.DECRYPT_MODE, keyPublic);
return cipher.doFinal(data);
}
/**
* 使用私钥进行解密
*/
public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception {
// 得到私钥
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory kf = KeyFactory.getInstance(RSA);
PrivateKey keyPrivate = kf.generatePrivate(keySpec);
// 解密数据
Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
cp.init(Cipher.DECRYPT_MODE, keyPrivate);
byte[] arr = cp.doFinal(encrypted);
return arr;
}
/**
* 用公钥对字符串进行分段加密
*/
public static byte[] encryptByPublicKeyForSpilt(byte[] data, byte[] publicKey) throws Exception {
int dataLen = data.length;
if (dataLen <= DEFAULT_BUFFERSIZE) {
return encryptByPublicKey(data, publicKey);
}
List allBytes = new ArrayList(2048);
int bufIndex = 0;
int subDataLoop = 0;
byte[] buf = new byte[DEFAULT_BUFFERSIZE];
for (int i = 0; i < dataLen; i++) {
buf[bufIndex] = data[i];
if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) {
subDataLoop++;
if (subDataLoop != 1) {
for (byte b : DEFAULT_SPLIT) {
allBytes.add(b);
}
}
byte[] encryptBytes = encryptByPublicKey(buf, publicKey);
for (byte b : encryptBytes) {
allBytes.add(b);
}
bufIndex = 0;
if (i == dataLen - 1) {
buf = null;
} else {
buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)];
}
}
}
byte[] bytes = new byte[allBytes.size()];
{
int i = 0;
for (Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
return bytes;
}
/**
* 分段加密
*
* @param data 要加密的原始数据
* @param privateKey 秘钥
*/
public static byte[] encryptByPrivateKeyForSpilt(byte[] data, byte[] privateKey) throws Exception {
int dataLen = data.length;
if (dataLen <= DEFAULT_BUFFERSIZE) {
return encryptByPrivateKey(data, privateKey);
}
List allBytes = new ArrayList(2048);
int bufIndex = 0;
int subDataLoop = 0;
byte[] buf = new byte[DEFAULT_BUFFERSIZE];
for (int i = 0; i < dataLen; i++) {
buf[bufIndex] = data[i];
if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) {
subDataLoop++;
if (subDataLoop != 1) {
for (byte b : DEFAULT_SPLIT) {
allBytes.add(b);
}
}
byte[] encryptBytes = encryptByPrivateKey(buf, privateKey);
for (byte b : encryptBytes) {
allBytes.add(b);
}
bufIndex = 0;
if (i == dataLen - 1) {
buf = null;
} else {
buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)];
}
}
}
byte[] bytes = new byte[allBytes.size()];
{
int i = 0;
for (Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
return bytes;
}
/**
* 公钥分段解密
*
* @param encrypted 待解密数据
* @param publicKey 密钥
*/
public static byte[] decryptByPublicKeyForSpilt(byte[] encrypted, byte[] publicKey) throws Exception {
int splitLen = DEFAULT_SPLIT.length;
if (splitLen <= 0) {
return decryptByPublicKey(encrypted, publicKey);
}
int dataLen = encrypted.length;
List allBytes = new ArrayList(1024);
int latestStartIndex = 0;
for (int i = 0; i < dataLen; i++) {
byte bt = encrypted[i];
boolean isMatchSplit = false;
if (i == dataLen - 1) {
// 到data的最后了
byte[] part = new byte[dataLen - latestStartIndex];
System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
byte[] decryptPart = decryptByPublicKey(part, publicKey);
for (byte b : decryptPart) {
allBytes.add(b);
}
latestStartIndex = i + splitLen;
i = latestStartIndex - 1;
} else if (bt == DEFAULT_SPLIT[0]) {
// 这个是以split[0]开头
if (splitLen > 1) {
if (i + splitLen < dataLen) {
// 没有超出data的范围
for (int j = 1; j < splitLen; j++) {
if (DEFAULT_SPLIT[j] != encrypted[i + j]) {
break;
}
if (j == splitLen - 1) {
// 验证到split的最后一位,都没有break,则表明已经确认是split段
isMatchSplit = true;
}
}
}
} else {
// split只有一位,则已经匹配了
isMatchSplit = true;
}
}
if (isMatchSplit) {
byte[] part = new byte[i - latestStartIndex];
System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
byte[] decryptPart = decryptByPublicKey(part, publicKey);
for (byte b : decryptPart) {
allBytes.add(b);
}
latestStartIndex = i + splitLen;
i = latestStartIndex - 1;
}
}
byte[] bytes = new byte[allBytes.size()];
{
int i = 0;
for (Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
return bytes;
}
/**
* 使用私钥分段解密
*/
public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted, byte[] privateKey) throws Exception {
int splitLen = DEFAULT_SPLIT.length;
if (splitLen <= 0) {
return decryptByPrivateKey(encrypted, privateKey);
}
int dataLen = encrypted.length;
List allBytes = new ArrayList(1024);
int latestStartIndex = 0;
for (int i = 0; i < dataLen; i++) {
byte bt = encrypted[i];
boolean isMatchSplit = false;
if (i == dataLen - 1) {
// 到data的最后了
byte[] part = new byte[dataLen - latestStartIndex];
System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
byte[] decryptPart = decryptByPrivateKey(part, privateKey);
for (byte b : decryptPart) {
allBytes.add(b);
}
latestStartIndex = i + splitLen;
i = latestStartIndex - 1;
} else if (bt == DEFAULT_SPLIT[0]) {
// 这个是以split[0]开头
if (splitLen > 1) {
if (i + splitLen < dataLen) {
// 没有超出data的范围
for (int j = 1; j < splitLen; j++) {
if (DEFAULT_SPLIT[j] != encrypted[i + j]) {
break;
}
if (j == splitLen - 1) {
// 验证到split的最后一位,都没有break,则表明已经确认是split段
isMatchSplit = true;
}
}
}
} else {
// split只有一位,则已经匹配了
isMatchSplit = true;
}
}
if (isMatchSplit) {
byte[] part = new byte[i - latestStartIndex];
System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
byte[] decryptPart = decryptByPrivateKey(part, privateKey);
for (byte b : decryptPart) {
allBytes.add(b);
}
latestStartIndex = i + splitLen;
i = latestStartIndex - 1;
}
}
byte[] bytes = new byte[allBytes.size()];
{
int i = 0;
for (Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
return bytes;
}
public static final String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAj9O5dd2u4JWV6ca/Vn9Q7x4Y0nSqzOPq\n" +
"tqYc3H3e2Ld7+1yInU4HsuYlg1uvgRr7msztyI0jRY9iZaIYhL3aPenbA9PnyxiAw1s7Pl8NwjFe\n" +
"5fT2uLynu4wkrqA5sLMHVt/L2grAcp9C14Eo5CVuXtUk7JEqfVQoQ2SWj1N89Oe/Ubtgbv0j2Bdr\n" +
"DwdW8+l+qIXA7AKRBh+HcdpHxnkVZDKfzBMNea7KjfFrqUvC6Q4GjbXG65sQ4rI/gX0iOD0BGlsF\n" +
"0MKBLkbCmAW4DP6QaMsqbgsO3aMCvVHcn6MQvmPbfFA5uH1uMRhydr+m2XvggUS6YHm1tfCoYvby\n" +
"BTcMMwIDAQAB";
public static final String PRIVATE_KEY = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCP07l13a7glZXpxr9Wf1DvHhjS\n" +
"dKrM4+q2phzcfd7Yt3v7XIidTgey5iWDW6+BGvuazO3IjSNFj2JlohiEvdo96dsD0+fLGIDDWzs+\n" +
"Xw3CMV7l9Pa4vKe7jCSuoDmwswdW38vaCsByn0LXgSjkJW5e1STskSp9VChDZJaPU3z0579Ru2Bu\n" +
"/SPYF2sPB1bz6X6ohcDsApEGH4dx2kfGeRVkMp/MEw15rsqN8WupS8LpDgaNtcbrmxDisj+BfSI4\n" +
"PQEaWwXQwoEuRsKYBbgM/pBoyypuCw7dowK9UdyfoxC+Y9t8UDm4fW4xGHJ2v6bZe+CBRLpgebW1\n" +
"8Khi9vIFNwwzAgMBAAECggEARRF3zpJWmKM9CrbWy8L4KtxZLze3jg0lefDrizcm/QugDmWxdVkz\n" +
"eUXsXdh5v5YlnYEr71NXzN++cPAWtig11eWnt37boTxzGV2GZb1f7hGncObiVHTEV9xFAVcQXTqc\n" +
"G6v9SQhAwsqYXsU3zdfr2L6irLhJn0X6z+JOKyX8q96h1eZJVvGm0bQQTtIDAVHi0YpHt2rw/XBK\n" +
"u4hYaLl8mxUU1e9g/HX6wz7GfzJSgIhMt0xbpJ19os0FT9Zh0OKgcUsN54D2Bf/ZGg/G2+QHRZX6\n" +
"EE6bM7taThYtYi6wEAHaG0SsuUEfDtFLlGv5U5Xer1YvDoyRS9SRQJbtNDArAQKBgQDu3njuXprb\n" +
"O16A8A1msuF+ncHBFBsdfxR/EUue+K25zyAwFMHS0GglfDX1nib09G47TbWbCflb35WSstHIfh09\n" +
"anhneBk09NpMqZAaNaEtujBYV62VloD5EzWW8ZyEzghCUs9//76tyyl3BD0c2eblpeFqSsK3PE68\n" +
"mNtOe4RkyQKBgQCaJFL7AGqhmxJwijLtn70huO0uSs17ye2u3qUkkL1je/CZRg4ESx9pYv8wTQ6J\n" +
"FZgB6kozjVobkOLS1f4cXlWBJlskP0qzX+ZJNdaRpITLX14LbmeIGHyi5sFWAqdCrS+oBbjiWDF5\n" +
"VpLA1Z7t9IalLXirijt8Qmb87U+3OtmTGwKBgEcxnZ+GKOeAqWkKoyPh2t2PDWmLoY1IDAbXU8+c\n" +
"1MKVnkVWWnKH1RKfE8ISEhBeLeCVB7Se42hjmkPv8iCsnfBpJFvKatDizZGd1CpLo69qV/BsqXr1\n" +
"MZmLBSTo/DqE4edKoTfINL+91qz3YXOQ6oW1zBqPD7vnSJxjfrHElLApAoGAUx+vmChbWJcV1JbS\n" +
"bA6uodbmIQa51T3J7XmnuRZM669UynNa77nLULvQPi3v3sFEXhQIu9BIfYEesPAxvv6oQaN7lwqC\n" +
"sETRHT3pXlVIP5xITQXW0y/RVs/2BvobVPusLYIYeAdzdqnXLiKFOHGbgswIvQkolxQAEfmv+XHF\n" +
"D20CgYAcKij5wyvIAdCR7uDagIRYL4NFkuOFUPRrdh7mz+pw/aDhPGWbGTAl7VPPk1ixJA5vweuf\n" +
"awOyoe4gZKGXVx8wqJhvUeL8ExgE45IX8xIjmBXBZEgGY4xlqBM5qFgP0jqKi4zPPNP9I0ga1sCQ\n" +
"dj2rH2JUe8VW5tnfKO7ICy12Ng==";
/**
* 通过字符串生成私钥
*/
public static PrivateKey getPrivateKey(String privateKeyData) {
PrivateKey privateKey = null;
try {
byte[] decodeKey = Base64Decoder.decodeToBytes(privateKeyData);
PKCS8EncodedKeySpec x509 = new PKCS8EncodedKeySpec(decodeKey);//创建x509证书封装类
KeyFactory keyFactory = KeyFactory.getInstance("RSA");//指定RSA
privateKey = keyFactory.generatePrivate(x509);//生成私钥
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return privateKey;
}
/**
* 通过字符串生成公钥
*/
public static PublicKey getPublicKey(String publicKeyData) {
PublicKey publicKey = null;
try {
byte[] decodeKey = Base64Decoder.decodeToBytes(publicKeyData);
X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodeKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
publicKey = keyFactory.generatePublic(x509);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return publicKey;
}
public static void main(String[] args) throws Exception {
String jsonData = "abcdefghijklmnopqrstuvwxyz";
// KeyPair keyPair = RSAUtils.generateRSAKeyPair(RSAUtils.DEFAULT_KEY_SIZE);
// RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// 修改于 2017年5月2日14:35:18 #回复1楼评论 补上getPublicKey的实现 忘记贴了。
RSAPublicKey publicKey = (RSAPublicKey) getPublicKey(PUBLIC_KEY);
System.out.println("RSAUtils publicKey ---->" + Base64Encoder.encode(publicKey.getEncoded()));
RSAPrivateKey privateKey = (RSAPrivateKey) getPrivateKey(PRIVATE_KEY);
System.out.println("RSAUtils privateKey ---->" + Base64Encoder.encode(privateKey.getEncoded()));
//公钥加密
long start = System.currentTimeMillis();
byte[] encryptBytes = RSAUtils.encryptByPublicKeyForSpilt(jsonData.getBytes(), publicKey.getEncoded());
long end = System.currentTimeMillis();
System.out.println("RSAUtils public encrypt cost time---->" + (end - start));
String encryStr = Base64Encoder.encode(encryptBytes);
System.out.println("RSAUtils jsonData(encrypted public) ---->" + encryStr);
System.out.println("RSAUtils jsonData(encrypted public) length>" + encryStr.length());
//私钥解密
start = System.currentTimeMillis();
byte[] decryptBytes = RSAUtils.decryptByPrivateKeyForSpilt(Base64Decoder.decodeToBytes(encryStr), privateKey.getEncoded());
String decryStr = new String(decryptBytes);
end = System.currentTimeMillis();
System.out.println("RSAUtils private decrypt cost time---->" + (end - start));
System.out.println("RSAUtils jsonData(decrypted private) ---->" + decryStr);
//私钥加密
start = System.currentTimeMillis();
encryptBytes = RSAUtils.encryptByPrivateKeyForSpilt(jsonData.getBytes(), privateKey.getEncoded());
end = System.currentTimeMillis();
System.out.println("RSAUtils private encrypt cost time---->" + (end - start));
encryStr = Base64Encoder.encode(encryptBytes);
System.out.println("RSAUtils jsonData(encrypted private) ---->" + encryStr);
System.out.println("RSAUtils jsonData(encrypted private) length ---->" + encryStr.length());
//公钥解密
start = System.currentTimeMillis();
decryptBytes = RSAUtils.decryptByPublicKeyForSpilt(Base64Decoder.decodeToBytes(encryStr), publicKey.getEncoded());
decryStr = new String(decryptBytes);
end = System.currentTimeMillis();
System.out.println("RSAUtils public decrypt cost time---->" + (end - start));
System.out.println("RSAUtils jsonData(decrypted public) ---->" + decryStr);
}
运行结果
RSAUtils publicKey ---->MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAj9O5dd2u4JWV6ca/Vn9Q7x4Y0nSqzOPq
tqYc3H3e2Ld7+1yInU4HsuYlg1uvgRr7msztyI0jRY9iZaIYhL3aPenbA9PnyxiAw1s7Pl8NwjFe
5fT2uLynu4wkrqA5sLMHVt/L2grAcp9C14Eo5CVuXtUk7JEqfVQoQ2SWj1N89Oe/Ubtgbv0j2Bdr
DwdW8+l+qIXA7AKRBh+HcdpHxnkVZDKfzBMNea7KjfFrqUvC6Q4GjbXG65sQ4rI/gX0iOD0BGlsF
0MKBLkbCmAW4DP6QaMsqbgsO3aMCvVHcn6MQvmPbfFA5uH1uMRhydr+m2XvggUS6YHm1tfCoYvby
BTcMMwIDAQAB
RSAUtils privateKey ---->MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCP07l13a7glZXpxr9Wf1DvHhjS
dKrM4+q2phzcfd7Yt3v7XIidTgey5iWDW6+BGvuazO3IjSNFj2JlohiEvdo96dsD0+fLGIDDWzs+
Xw3CMV7l9Pa4vKe7jCSuoDmwswdW38vaCsByn0LXgSjkJW5e1STskSp9VChDZJaPU3z0579Ru2Bu
/SPYF2sPB1bz6X6ohcDsApEGH4dx2kfGeRVkMp/MEw15rsqN8WupS8LpDgaNtcbrmxDisj+BfSI4
PQEaWwXQwoEuRsKYBbgM/pBoyypuCw7dowK9UdyfoxC+Y9t8UDm4fW4xGHJ2v6bZe+CBRLpgebW1
8Khi9vIFNwwzAgMBAAECggEARRF3zpJWmKM9CrbWy8L4KtxZLze3jg0lefDrizcm/QugDmWxdVkz
eUXsXdh5v5YlnYEr71NXzN++cPAWtig11eWnt37boTxzGV2GZb1f7hGncObiVHTEV9xFAVcQXTqc
G6v9SQhAwsqYXsU3zdfr2L6irLhJn0X6z+JOKyX8q96h1eZJVvGm0bQQTtIDAVHi0YpHt2rw/XBK
u4hYaLl8mxUU1e9g/HX6wz7GfzJSgIhMt0xbpJ19os0FT9Zh0OKgcUsN54D2Bf/ZGg/G2+QHRZX6
EE6bM7taThYtYi6wEAHaG0SsuUEfDtFLlGv5U5Xer1YvDoyRS9SRQJbtNDArAQKBgQDu3njuXprb
O16A8A1msuF+ncHBFBsdfxR/EUue+K25zyAwFMHS0GglfDX1nib09G47TbWbCflb35WSstHIfh09
anhneBk09NpMqZAaNaEtujBYV62VloD5EzWW8ZyEzghCUs9//76tyyl3BD0c2eblpeFqSsK3PE68
mNtOe4RkyQKBgQCaJFL7AGqhmxJwijLtn70huO0uSs17ye2u3qUkkL1je/CZRg4ESx9pYv8wTQ6J
FZgB6kozjVobkOLS1f4cXlWBJlskP0qzX+ZJNdaRpITLX14LbmeIGHyi5sFWAqdCrS+oBbjiWDF5
VpLA1Z7t9IalLXirijt8Qmb87U+3OtmTGwKBgEcxnZ+GKOeAqWkKoyPh2t2PDWmLoY1IDAbXU8+c
1MKVnkVWWnKH1RKfE8ISEhBeLeCVB7Se42hjmkPv8iCsnfBpJFvKatDizZGd1CpLo69qV/BsqXr1
MZmLBSTo/DqE4edKoTfINL+91qz3YXOQ6oW1zBqPD7vnSJxjfrHElLApAoGAUx+vmChbWJcV1JbS
bA6uodbmIQa51T3J7XmnuRZM669UynNa77nLULvQPi3v3sFEXhQIu9BIfYEesPAxvv6oQaN7lwqC
sETRHT3pXlVIP5xITQXW0y/RVs/2BvobVPusLYIYeAdzdqnXLiKFOHGbgswIvQkolxQAEfmv+XHF
D20CgYAcKij5wyvIAdCR7uDagIRYL4NFkuOFUPRrdh7mz+pw/aDhPGWbGTAl7VPPk1ixJA5vweuf
awOyoe4gZKGXVx8wqJhvUeL8ExgE45IX8xIjmBXBZEgGY4xlqBM5qFgP0jqKi4zPPNP9I0ga1sCQ
dj2rH2JUe8VW5tnfKO7ICy12Ng==
RSAUtils public encrypt cost time---->726
RSAUtils jsonData(encrypted public) ---->amicP8WaCWY/Xm4hZy1ehTca2Tst+bNmM+tUakJVMkLklfsLQqxaZ9dBBZJP429zKj7ywGz8pjoh
a3umErQR1FDvtON4qJnzDY/PEXCod0OsCqCdRrD4fIhT8MgNWz+u5oKBMv48/wpzAPUXCdpeeRw4
HOyRJf6yM8E6SvalMPVRWVo3bFPy72OLAG3Gxys/seJLwbPsdX0q6FdEDleczDcZu63hv6fD0wBF
jN4BdK60Op7i+0bk7O6sVb5MqpzM2jUNCnW115SP67Fccwdm2alJ0BeR+ZfAa/SeeXkGP+r+nGlW
qmDRNz7t0MgseisC3ik+Rs8JBj3qyp252v+RCQ==
RSAUtils jsonData(encrypted public) length>348
RSAUtils private decrypt cost time---->0
RSAUtils jsonData(decrypted private) ---->abcdefghijklmnopqrstuvwxyz
RSAUtils private encrypt cost time---->16
RSAUtils jsonData(encrypted private) ---->WHDpMf3jkjnwFcaOSseMvJOejn8torogdK6lhr6yfkmBRlarbKk5te3pNchxxzJme5a/Xm21wKHl
ro3uxisROOzjUBGq+YtSHIq76jJ/nxNCXm7elQTzLacifsV0GZx2MBw/AnsfMEuSshhVKD4Zx5H4
/plsQzgHrbV9jxI+wi1hwbc3xTADvdRV4aqFJ6Wuz58PCpFFEgWpnZQ7OtlWrW4dwN2ESpgXGqqc
7zFTDYm8t8e9wOSYAot0bTzRoVsdn/2szTQhb7/m1H25DO4xddrwWvxNjANfTEnflXLuUj2GAAIg
ZirfLMOLa4RaN9DMI9e5qjVMveWAryPPLre2yw==
RSAUtils jsonData(encrypted private) length ---->348
RSAUtils public decrypt cost time---->0
RSAUtils jsonData(decrypted public) ---->abcdefghijklmnopqrstuvwxyz
文章知识主要参考
http://www.cnblogs.com/AloneSword/p/3326750.html
http://www.cnblogs.com/whoislcj/p/5473030.html
简单整理出完整可运行的Demo内容。以便日后复制。。。