打算写这个类用于spark插件加密对话消息用
RSA的Java实现不能一次加密很大的字符自己处理了一下见下面的代码
Base编码类用的是一个Public domain Base for java
其他的保存公钥到文件等简单的实现就不详细说了看代码吧
==============================================
import javasecurity*;
import javasecurityspecPKCSEncodedKeySpec;
import javasecurityspecXEncodedKeySpec;
import javautilHashMap;
import javautilMap;
import javaxcrypto*;
import javaio*;
public class Encryptor {
private static final String KEY_FILENAME = c:\\mykeydat;
private static final String OTHERS_KEY_FILENAME = c:\\Otherskeydat;
// private static final int KEY_SIZE = ;
// private static final int BLOCK_SIZE = ;
// private static final int OUTPUT_BLOCK_SIZE = ;
private static final int KEY_SIZE = ; //RSA key 是多少位的
private static final int BLOCK_SIZE = ; //一次RSA加密操作所允许的最大长度
//这个值与 KEY_SIZE 已经padding方法有关因为 的key的输出是key输出是字节
//可能个字节用于保存padding信息了所以最多可用的就只有字节了
private static final int OUTPUT_BLOCK_SIZE = ;
private SecureRandom secrand;
private Cipher rsaCipher;
private KeyPair keys;
private Map<String Key> allUserKeys;
public Encryptor() throws Exception {
try {
allUserKeys = new HashMap<String Key>();
secrand = new SecureRandom();
//SunJCE Provider 中只支持ECB mode试了一下只有PKCSPADDING可以直接还原原始数据
//NOPadding导致解压出来的都是blocksize长度的数据还要自己处理
//参见 l
//
//另外根据 OpenJDKbsrc(l)
// 中代码的注释使用RSA来加密大量数据不是一种标准的用法所以现有实现一次doFinal调用之进行一个RSA操作
//如果用doFinal来加密超过的一个操作所允许的长度数据将抛出异常
//根据keysize的长度典型的个长度的key和PKCSPADDING一起使用时
//一次doFinal调用只能加密个byte的数据(NOPadding 和 keysize时个字节长度)
//(长度的key和PKCSPADDING 最多允许字节一次)
//想用来加密大量数据的只能自己用其他办法实现了可能RSA加密速度比较慢吧要用AES才行
rsaCipher = CiphergetInstance(RSA/ECB/PKCSPADDING);
} catch (NoSuchAlgorithmException e) {
eprintStackTrace();
} catch (NoSuchPaddingException e) {
eprintStackTrace();
throw e;
}
ObjectInputStream in;
try {
in = new ObjectInputStream(new FileInputStream(KEY_FILENAME));
} catch (FileNotFoundException e) {
if (false == GenerateKeys())
{
throw e;
}
LoadKeys();
return;
}
keys = (KeyPair) inreadObject();
inclose();
LoadKeys();
}
/*
* 生成自己的公钥和私钥
*/
private Boolean GenerateKeys() {
try {
KeyPairGenerator keygen = KeyPairGeneratorgetInstance(RSA);
// secrand = new SecureRandom();
// sedSeed之后会造成 生成的密钥都是一样的
// secrandsetSeed(chatencrptorgetBytes()); // 初始化随机产生器
//key长度至少长度不过好像说现在用才算比较安全的了
keygeninitialize(KEY_SIZE secrand); // 初始化密钥生成器
keys = keygengenerateKeyPair(); // 生成密钥组
AddKey(me EncodeKey(keysgetPublic()));
} catch (NoSuchAlgorithmException e) {
eprintStackTrace();
return false;
}
ObjectOutputStream out;
try {
out = new ObjectOutputStream(new FileOutputStream(KEY_FILENAME));
} catch (IOException e) {
eprintStackTrace();
return false;
}
try {
outwriteObject(keys);
} catch (IOException e) {
eprintStackTrace();
return false;
} finally {
try {
outclose();
} catch (IOException e) {
eprintStackTrace();
return false;
}
}
return true;
}
public String EncryptMessage(String toUser String Message) throws IOException {
Key pubkey = allUserKeysget(toUser);
if ( pubkey == null )
{
throw new IOException(NoKeyForThisUser) ;
}
try {
//PublicKey pubkey = keysgetPublic();
rsaCipherinit(CipherENCRYPT_MODE pubkey secrand);
//Systemoutprintln(rsaCiphergetBlockSize()); 返回非block 加密算法来的?
//Systemoutprintln(MessagegetBytes(utf)length);
//byte[] encryptedData = rsaCipherdoFinal(MessagegetBytes(utf));
byte[] data = MessagegetBytes(utf);
int blocks = datalength / BLOCK_SIZE ;
int lastBlockSize = datalength % BLOCK_SIZE ;
byte [] encryptedData = new byte[ (lastBlockSize == ? blocks : blocks + )* OUTPUT_BLOCK_SIZE];
for (int i=; i < blocks; i++)
{
//int thisBlockSize = ( i + ) * BLOCK_SIZE > datalength ? datalength i * BLOCK_SIZE : BLOCK_SIZE ;
rsaCipherdoFinal(datai * BLOCK_SIZE BLOCK_SIZE encryptedData i * OUTPUT_BLOCK_SIZE);
}
if (lastBlockSize != ){
rsaCipherdoFinal(data blocks * BLOCK_SIZE lastBlockSizeencryptedData blocks * OUTPUT_BLOCK_SIZE);
}
//Systemoutprintln(encryptedlength); 如果要机密的数据不足/字节加密后补全成为变为长度的
//数量比较小时BaseGZIP产生的长度更长没什么优势
//Systemoutprintln(BaseencodeBytes(encryptedBaseGZIP)length());
//Systemoutprintln(BaseencodeBytes(encrypted)length());
//Systemoutprintln (rsaCiphergetOutputSize());
//这个getOutputSize 只对 输入小于最大的block时才能得到正确的结果其实就是补全 数据为/ 字节
return BaseencodeBytes(encryptedData);
} catch (InvalidKeyException e) {
eprintStackTrace();
throw new IOException(InvalidKey) ;
}catch (ShortBufferException e) {
eprintStackTrace();
throw new IOException(ShortBuffer) ;
}
catch (UnsupportedEncodingException e) {
eprintStackTrace();
throw new IOException(UnsupportedEncoding) ;
} catch (IllegalBlockSizeException e) {
eprintStackTrace();
throw new IOException(IllegalBlockSize) ;
} catch (BadPaddingException e) {
eprintStackTrace();
throw new IOException(BadPadding) ;
}finally {
//catch 中 return 或者throw之前都会先调用一下这里
}
}
public String DecryptMessage(String Message) throws IOException {
byte[] decoded = Basedecode(Message);
PrivateKey prikey = keysgetPrivate();
try {
rsaCipherinit(CipherDECRYPT_MODE prikey secrand);
int blocks = decodedlength / OUTPUT_BLOCK_SIZE;
ByteArrayOutputStream decodedStream = new ByteArrayOutputStream(decodedlength);
for (int i = ;i < blocks ; i ++ )
{
decodedStreamwrite (rsaCipherdoFinal(decodedi * OUTPUT_BLOCK_SIZE OUTPUT_BLOCK_SIZE));
}
return new String(decodedStreamtoByteArray() UTF);
} catch (InvalidKeyException e) {
eprintStackTrace();
throw new IOException(InvalidKey);
} catch (UnsupportedEncodingException e) {
eprintStackTrace();
throw new IOException(UnsupportedEncoding);
} catch (IllegalBlockSizeException e) {
eprintStackTrace();
throw new IOException(IllegalBlockSize);
} catch (BadPaddingException e) {
eprintStackTrace();
throw new IOException(BadPadding);
} finally {
// catch 中 return 或者throw之前都会先调用一下这里
}
}
public boolean AddKey(String user String key) {
PublicKey publickey;
try {
publickey = DecodePublicKey(key);
} catch (Exception e) {
return false;
}
allUserKeysput(user publickey);
SaveKeys();
return true;
}
private boolean LoadKeys() {
BufferedReader input;
try {
input = new BufferedReader(new InputStreamReader(
new FileInputStream(OTHERS_KEY_FILENAME)));
} catch (FileNotFoundException e) {
// eprintStackTrace();
return false;
}
try {
allUserKeysclear();
String line;
while ((line = inputreadLine()) != null) {
String[] temp = linesplit(\\|);
String user = temp[];
PublicKey key = DecodePublicKey(temp[]);
allUserKeysput(user key);
}
} catch (Exception e) {
return false;
} finally {
try {
inputclose();
} catch (Exception e) {
return false;
}
}
return true;
}
private boolean SaveKeys() {
FileWriter output;
try {
output = new FileWriter(OTHERS_KEY_FILENAME);
} catch (IOException e) {
// printStackTrace();
return false;
}
try {
for (String user : allUserKeyskeySet()) {
Key key = allUserKeysget(user);
outputwrite(user + | + EncodeKey(key) + \n);
}
} catch (IOException e) {
// printStackTrace();
return false;
} finally {
try {
outputclose();
} catch (Exception e) {
return false;
}
}
return true;
}
/**
* 解密base编码得到公钥
*
* @param key
* 密钥字符串(经过base编码)
* @throws Exception
*/
public static PublicKey DecodePublicKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = Basedecode(key);
XEncodedKeySpec keySpec = new XEncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactorygetInstance(RSA);
PublicKey publicKey = keyFactorygeneratePublic(keySpec);
return publicKey;
}
/**
* 解密base编码得到私钥
*
* @param key
* 密钥字符串(经过base编码)
* @throws Exception
*/
public static PrivateKey DecodePrivateKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = Basedecode(key);
PKCSEncodedKeySpec keySpec = new PKCSEncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactorygetInstance(RSA);
PrivateKey privateKey = keyFactorygeneratePrivate(keySpec);
return privateKey;
}
/**
* 编码key为base字符串
*
* @return
*/
public static String EncodeKey(Key key) {
byte[] keyBytes = keygetEncoded();
// Systemoutprint(keygetFormat()) ;
String s = BaseencodeBytes(keyBytes);
return s;
}
}
===============测试类============================
import javautilIterator ;
import javasecuritySecurity ;
import javasecurityProvider ;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// Provider [ ] providers = SecuritygetProviders () ;
// for ( int i = ; i < providerslength ; i++ )
// {
// String name = providers[i]getName () ;
// String info = providers[i]getInfo () ;
// double version = providers[i]getVersion () ;
// Systemoutprintln ( ) ;
// Systemoutprintln ( name: + name ) ;
// Systemoutprintln ( info: + info ) ;
// Systemoutprintln ( version: + version ) ;
//
// for ( Iterator iter = providers[i]keySet(erator () ; iterhasNext () ; )
// {
// String key = (String) iternext () ;
// Systemoutprintln ( \t + key +
// \t +
// providers[i]getProperty ( key ) ) ;
// }
//
// Systemoutprintln (
//
// );
// }
//
// int i = / ;
// Systemoutprintln(i);
// i = / ;
// Systemoutprintln(i);
// i = / ;
// Systemoutprintln(i);
// i = / ;
// Systemoutprintln(i);
//String str = widebriht的测试哈哈^_^;
//String str = MIIBIjANBgkqhkiGwBAQEFAAOCAQAMIIBCgKCAQEAdYTvxxgsuSmgqJzPWzSOziMDnOV+tAxQGumNAJKcBxOlDhQlqTGRnUoqIpzbrioFJBtMswAeA+pfpJhFyqodIfrrIYPUgwRlLozGAhuCBOADQNKEgUgOTQ/joEYoYPCHKx/vYQncOeaxOCqcXBWViwWgPrgqjCarQLMedUNMCYcXZGvqIyJsFjuLsNaKkyfjIqquFzhjvIEDCtrMNyTvVcoVrDGTECKfJftoeCTXrhcgzMBdaGDXFQezQIepMdPAT+kga/qJbILMwyCDhwPmHUNQAmdMpJbZTTwIDAQAB;
String str = MIIBIjANBgkqhkiGwBMIIBIjANBgkqhkiGwBMIIBIjANBgkqhkiGwBMIIBIjANBgkqhkiGwBMIIBIjANBgkqhkiGwBMIIBIjANBgkqhkiGwBMIIBIjANBgkqhkiGwBMIIBIjANBgkqhkiGwBMIIBIjANBgkqhkiGwBMIIBIjANBgkqhkiGwBMIIBIjANBgkqhkiGwBMIIBIjANBgkqhkiGwBddddd;
try {
Encryptor ddd = new Encryptor();
str = dddEncryptMessage(me str);
// Systemoutprintln(strlength());
String str = jhahahh my god ;
str = dddEncryptMessage(me str);
str = dddDecryptMessage(str);
str = dddDecryptMessage(str);
} catch (Exception e) {
if (egetMessage() == NoKeyForThisUser) {
Systemoutprintln(NoKeyForThisUser);
}
}
// str = dddDecryptMessage(
// inIyPfFXtoNWXuYLBbTkIaaxZFzgWuMfYTqpTbUUQNTiKlXnS+WShC/ZGLnoXvOsDmiJ+zI/WTgvOOWXE+G+edGzhbfRGPxhGMJply/FsIErsKgZmybEREFIP/bxGmrZhyj/NwZlnqUg=);
//Systemoutprintln(str);
}
}