Broadview 2009-08-15
/**
*RSA工具类。提供加密,解密,生成密钥对等方法。
*需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。
*RSA加密原理概述
*RSA的安全性依赖于大数的分解,公钥和私钥都是两个大素数(大于100的十进制位)的函数。
*据猜测,从一个密钥和密文推断出明文的难度等同于分解两个大素数的积
*===================================================================
*(该算法的安全性未得到理论的证明)
*===================================================================
*密钥的产生:
*1.选择两个大素数p,q,计算n=p*q;
*2.随机选择加密密钥e,要求e和(p-1)*(q-1)互质
*3.利用Euclid算法计算解密密钥d,使其满足e*d=1(mod(p-1)*(q-1))(其中n,d也要互质)
*4:至此得出公钥为(n,e)私钥为(n,d)
*===================================================================
*加解密方法:
*1.首先将要加密的信息m(二进制表示)分成等长的数据块m1,m2,...,mi块长s(尽可能大),其中2^s<n
*2:对应的密文是:ci=mi^e(modn)
*3:解密时作如下计算:mi=ci^d(modn)
*===================================================================
*RSA速度
*由于进行的都是大数计算,使得RSA最快的情况也比DES慢上100倍,无论是软件还是硬件实现。
*速度一直是RSA的缺陷。一般来说只用于少量数据加密。
*文件名:RSAUtil.java<br>
*@author董利伟<br>
*版本:<br>
*描述:<br>
*创建时间:2008-9-23下午09:58:16<br>
*文件描述:<br>
*修改者:<br>
*修改日期:<br>
*修改描述:<br>
*/
public class RSAUtil {//密钥对
privateKeyPairkeyPair=null;
/**
*初始化密钥对
*/
publicRSAUtil(){
try{
this.keyPair=this.generateKeyPair();
}catch(Exceptione){
e.printStackTrace();
}
}
/**
*生成密钥对
*@returnKeyPair
*@throwsException
*/
privateKeyPairgenerateKeyPair()throwsException{
try{
KeyPairGeneratorkeyPairGen=KeyPairGenerator.getInstance("RSA",neworg.bouncycastle.jce.provider.BouncyCastleProvider());
//这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低
finalintKEY_SIZE=1024;
keyPairGen.initialize(KEY_SIZE,newSecureRandom());
KeyPairkeyPair=keyPairGen.genKeyPair();
returnkeyPair;
}catch(Exceptione){
thrownewException(e.getMessage());
}
}/**
*生成公钥
*@parammodulus
*@parampublicExponent
*@returnRSAPublicKey
*@throwsException
*/
privateRSAPublicKeygenerateRSAPublicKey(byte[]modulus,byte[]publicExponent)throwsException{
KeyFactorykeyFac=null;
try{
keyFac=KeyFactory.getInstance("RSA",neworg.bouncycastle.jce.provider.BouncyCastleProvider());
}catch(NoSuchAlgorithmExceptionex){
thrownewException(ex.getMessage());
}
RSAPublicKeySpecpubKeySpec=newRSAPublicKeySpec(newBigInteger(modulus),newBigInteger(publicExponent));
try{
return(RSAPublicKey)keyFac.generatePublic(pubKeySpec);
}catch(InvalidKeySpecExceptionex){
thrownewException(ex.getMessage());
}
}/**
*生成私钥
*@parammodulus
*@paramprivateExponent
*@returnRSAPrivateKey
*@throwsException
*/
privateRSAPrivateKeygenerateRSAPrivateKey(byte[]modulus,byte[]privateExponent)throwsException{
KeyFactorykeyFac=null;
try{
keyFac=KeyFactory.getInstance("RSA",neworg.bouncycastle.jce.provider.BouncyCastleProvider());
}catch(NoSuchAlgorithmExceptionex){
thrownewException(ex.getMessage());
}
RSAPrivateKeySpecpriKeySpec=newRSAPrivateKeySpec(newBigInteger(modulus),newBigInteger(privateExponent));
try{
return(RSAPrivateKey)keyFac.generatePrivate(priKeySpec);
}catch(InvalidKeySpecExceptionex){
thrownewException(ex.getMessage());
}
}/**
*加密
*@paramkey加密的密钥
*@paramdata待加密的明文数据
*@return加密后的数据
*@throwsException
*/
publicbyte[]encrypt(Keykey,byte[]data)throwsException{
try{
Ciphercipher=Cipher.getInstance("RSA",neworg.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE,key);
//获得加密块大小,如:加密前数据为128个byte,而key_size=1024加密块大小为127byte,加密后为128个byte;
//因此共有2个加密块,第一个127byte第二个为1个byte
intblockSize=cipher.getBlockSize();
intoutputSize=cipher.getOutputSize(data.length);//获得加密块加密后块大小
intleavedSize=data.length%blockSize;
intblocksSize=leavedSize!=0?data.length/blockSize+1:data.length/blockSize;
byte[]raw=newbyte[outputSize*blocksSize];
inti=0;
while(data.length-i*blockSize>0){
if(data.length-i*blockSize>blockSize)
cipher.doFinal(data,i*blockSize,blockSize,raw,i*outputSize);
else
cipher.doFinal(data,i*blockSize,data.length-i*blockSize,raw,i*outputSize);
//这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到ByteArrayOutputStream中
//,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了OutputSize所以只好用dofinal方法。
i++;
}
returnraw;
}catch(Exceptione){
thrownewException(e.getMessage());
}
}/**
*解密
*@paramkey解密的密钥
*@paramraw已经加密的数据
*@return解密后的明文
*@throwsException
*/
publicbyte[]decrypt(Keykey,byte[]raw)throwsException{
try{
Ciphercipher=Cipher.getInstance("RSA",neworg.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(cipher.DECRYPT_MODE,key);
intblockSize=cipher.getBlockSize();
ByteArrayOutputStreambout=newByteArrayOutputStream(64);
intj=0;
while(raw.length-j*blockSize>0){
bout.write(cipher.doFinal(raw,j*blockSize,blockSize));
j++;
}
returnbout.toByteArray();
}catch(Exceptione){
thrownewException(e.getMessage());
}
}
/**
*返回公钥
*@return
*@throwsException
*/
publicRSAPublicKeygetRSAPublicKey()throwsException{
//获取公钥
RSAPublicKeypubKey=(RSAPublicKey)keyPair.getPublic();
//获取公钥系数(字节数组形式)
byte[]pubModBytes=pubKey.getModulus().toByteArray();
//返回公钥公用指数(字节数组形式)
byte[]pubPubExpBytes=pubKey.getPublicExponent().toByteArray();
//生成公钥
RSAPublicKeyrecoveryPubKey=this.generateRSAPublicKey(pubModBytes,pubPubExpBytes);
returnrecoveryPubKey;
}
/**
*获取私钥
*@return
*@throwsException
*/
publicRSAPrivateKeygetRSAPrivateKey()throwsException{
//获取私钥
RSAPrivateKeypriKey=(RSAPrivateKey)keyPair.getPrivate();
//返回私钥系数(字节数组形式)
byte[]priModBytes=priKey.getModulus().toByteArray();
//返回私钥专用指数(字节数组形式)
byte[]priPriExpBytes=priKey.getPrivateExponent().toByteArray();
//生成私钥
RSAPrivateKeyrecoveryPriKey=this.generateRSAPrivateKey(priModBytes,priPriExpBytes);
returnrecoveryPriKey;
}
/**
*测试
*@paramargs
*@throwsException
*/
publicstaticvoidmain(String[]args)throwsException{
RSAUtilrsa=newRSAUtil();
Stringstr="董利伟";
RSAPublicKeypubKey=rsa.getRSAPublicKey();
RSAPrivateKeypriKey=rsa.getRSAPrivateKey();
System.out.println("加密后=="+newString(rsa.encrypt(pubKey,str.getBytes())));
System.out.println("解密后=="+newString(rsa.decrypt(priKey,rsa.encrypt(pubKey,str.getBytes()))));
}
}