該工具類中用到了BASE64,需要借助第三方類庫:javabase64-1.3.1.jar注意:RSA加密明文最大長度117字節,解密要求密文最大長度為128字節,所以在加密和解密的過程中需要分塊進行。
RSA加密對明文的長度是有限制的,如果加密數據過大會拋出如下異常: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.javapackage?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;
/**
*?
*?RSA公鑰/私鑰/簽名工具包
*?
*?
*?羅納德·李維斯特(Ron?[R]ivest)、阿迪·薩莫爾(Adi?[S]hamir)和倫納德·阿德曼(Leonard?[A]dleman)
*?
*?
*?字符串格式的密鑰在未在特殊說明情況下都為BASE64編碼格式
*?由于非對稱加密速度極其緩慢,一般文件不使用它來加密而是使用對稱加密,
*?非對稱加密算法可以用來對對稱加密的密鑰加密,這樣保證密鑰的安全也就保證了數據的安全
*?
*
*?@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;
/**
*?
*?生成密鑰對(公鑰和私鑰)
*?
*
*?@return
*?@throws?Exception
*/
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;
}
/**
*?
*?用私鑰對信息生成數字簽名
*?
*
*?@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());
}
/**
*?
*?校驗數字簽名
*?
*
*?@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));
}
/**
*?
*?私鑰解密
*?
*
*?@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;
}
/**
*?
*?公鑰解密
*?
*
*?@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;
}
/**
*?
*?公鑰加密
*?
*
*?@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;
}
/**
*?
*?私鑰加密
*?
*
*?@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;
}
/**
*?
*?獲取私鑰
*?
*
*?@param?keyMap?密鑰對
*?@return
*?@throws?Exception
*/
public?static?String?getPrivateKey(Map?keyMap)
throws?Exception?{
Key?key?=?(Key)?keyMap.get(PRIVATE_KEY);
return?Base64Utils.encode(key.getEncoded());
}
/**
*?
*?獲取公鑰
*?
*
*?@param?keyMap?密鑰對
*?@return
*?@throws?Exception
*/
public?static?String?getPublicKey(Map?keyMap)
throws?Exception?{
Key?key?=?(Key)?keyMap.get(PUBLIC_KEY);
return?Base64Utils.encode(key.getEncoded());
}
}
Base64Utils.javaimport?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;
/**
*?
*?BASE64編碼解碼工具包
*?
*?
*?依賴javabase64-1.3.1.jar
*?
*
*?@author?IceWee
*?@date?2012-5-19
*?@version?1.0
*/
public?class?Base64Utils?{
/**
*?文件讀取緩沖區大小
*/
private?static?final?int?CACHE_SIZE?=?1024;
/**
*?
*?BASE64字符串解碼為二進制數據
*?
*
*?@param?base64
*?@return
*?@throws?Exception
*/
public?static?byte[]?decode(String?base64)?throws?Exception?{
return?Base64.decode(base64.getBytes());
}
/**
*?
*?二進制數據編碼為BASE64字符串
*?
*
*?@param?bytes
*?@return
*?@throws?Exception
*/
public?static?String?encode(byte[]?bytes)?throws?Exception?{
return?new?String(Base64.encode(bytes));
}
/**
*?
*?將文件編碼為BASE64字符串
*?
*?
*?大文件慎用,可能會導致內存溢出
*?
*
*?@param?filePath?文件絕對路徑
*?@return
*?@throws?Exception
*/
public?static?String?encodeFile(String?filePath)?throws?Exception?{
byte[]?bytes?=?fileToByte(filePath);
return?encode(bytes);
}
/**
*?
*?BASE64字符串轉回文件
*?
*
*?@param?filePath?文件絕對路徑
*?@param?base64?編碼字符串
*?@throws?Exception
*/
public?static?void?decodeToFile(String?filePath,?String?base64)?throws?Exception?{
byte[]?bytes?=?decode(base64);
byteArrayToFile(bytes,?filePath);
}
/**
*?
*?文件轉換為二進制數組
*?
*
*?@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;
}
/**
*?
*?二進制數據寫文件
*?
*
*?@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.javaimport?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);
}
}