公钥私解和私钥公解的应用RSA的加密

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()))));

}

}

相关推荐

cindycinderella / 0评论 2020-01-14