Java加密技术(四)——非对称加密算法RSA

Java非对称加密算法rsa

接下来我们介绍典型的非对称加密算法——RSA

RSA

这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:RonRivest,AdiShamir和LeonardAdleman。

这种加密算法的特点主要是密钥的变化,上文我们看到DES只有一个密钥。相当于只有一把钥匙,如果这把钥匙丢了,数据也就不安全了。RSA同时有两把钥匙,公钥与私钥。同时支持数字签名。数字签名的意义在于,对传输过来的数据进行校验。确保数据在传输工程中不被修改。

流程分析:

甲方构建密钥对儿,将公钥公布给乙方,将私钥保留。

甲方使用私钥加密数据,然后用私钥对加密后的数据签名,发送给乙方签名以及加密后的数据;乙方使用公钥、签名来验证待解密数据是否有效,如果有效使用公钥对数据解密。

乙方使用公钥加密数据,向甲方发送经过加密后的数据;甲方获得加密数据,通过私钥解密。

按如上步骤给出序列图,如下:

通过java代码实现如下:Coder类见Java加密技术(一)

Java代码收藏代码

importjava.security.Key;

importjava.security.KeyFactory;

importjava.security.KeyPair;

importjava.security.KeyPairGenerator;

importjava.security.PrivateKey;

importjava.security.PublicKey;

importjava.security.Signature;

importjava.security.interfaces.RSAPrivateKey;

importjava.security.interfaces.RSAPublicKey;

importjava.security.spec.PKCS8EncodedKeySpec;

importjava.security.spec.X509EncodedKeySpec;

importjava.util.HashMap;

importjava.util.Map;

importjavax.crypto.Cipher;

/**

*RSA安全编码组件

*

*@author梁栋

*@version1.0

*@since1.0

*/

publicabstractclassRSACoderextendsCoder{

publicstaticfinalStringKEY_ALGORITHM="RSA";

publicstaticfinalStringSIGNATURE_ALGORITHM="MD5withRSA";

privatestaticfinalStringPUBLIC_KEY="RSAPublicKey";

privatestaticfinalStringPRIVATE_KEY="RSAPrivateKey";

/**

*用私钥对信息生成数字签名

*

*@paramdata

*加密数据

*@paramprivateKey

*私钥

*

*@return

*@throwsException

*/

publicstaticStringsign(byte[]data,StringprivateKey)throwsException{

//解密由base64编码的私钥

byte[]keyBytes=decryptBASE64(privateKey);

//构造PKCS8EncodedKeySpec对象

PKCS8EncodedKeySpecpkcs8KeySpec=newPKCS8EncodedKeySpec(keyBytes);

//KEY_ALGORITHM指定的加密算法

KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);

//取私钥匙对象

PrivateKeypriKey=keyFactory.generatePrivate(pkcs8KeySpec);

//用私钥对信息生成数字签名

Signaturesignature=Signature.getInstance(SIGNATURE_ALGORITHM);

signature.initSign(priKey);

signature.update(data);

returnencryptBASE64(signature.sign());

}

/**

*校验数字签名

*

*@paramdata

*加密数据

*@parampublicKey

*公钥

*@paramsign

*数字签名

*

*@return校验成功返回true失败返回false

*@throwsException

*

*/

publicstaticbooleanverify(byte[]data,StringpublicKey,Stringsign)

throwsException{

//解密由base64编码的公钥

byte[]keyBytes=decryptBASE64(publicKey);

//构造X509EncodedKeySpec对象

X509EncodedKeySpeckeySpec=newX509EncodedKeySpec(keyBytes);

//KEY_ALGORITHM指定的加密算法

KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);

//取公钥匙对象

PublicKeypubKey=keyFactory.generatePublic(keySpec);

Signaturesignature=Signature.getInstance(SIGNATURE_ALGORITHM);

signature.initVerify(pubKey);

signature.update(data);

//验证签名是否正常

returnsignature.verify(decryptBASE64(sign));

}

/**

*解密<br>

*用私钥解密

*

*@paramdata

*@paramkey

*@return

*@throwsException

*/

publicstaticbyte[]decryptByPrivateKey(byte[]data,Stringkey)

throwsException{

//对密钥解密

byte[]keyBytes=decryptBASE64(key);

//取得私钥

PKCS8EncodedKeySpecpkcs8KeySpec=newPKCS8EncodedKeySpec(keyBytes);

KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);

KeyprivateKey=keyFactory.generatePrivate(pkcs8KeySpec);

//对数据解密

Ciphercipher=Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.DECRYPT_MODE,privateKey);

returncipher.doFinal(data);

}

/**

*解密<br>

*用公钥解密

*

*@paramdata

*@paramkey

*@return

*@throwsException

*/

publicstaticbyte[]decryptByPublicKey(byte[]data,Stringkey)

throwsException{

//对密钥解密

byte[]keyBytes=decryptBASE64(key);

//取得公钥

X509EncodedKeySpecx509KeySpec=newX509EncodedKeySpec(keyBytes);

KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);

KeypublicKey=keyFactory.generatePublic(x509KeySpec);

//对数据解密

Ciphercipher=Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.DECRYPT_MODE,publicKey);

returncipher.doFinal(data);

}

/**

*加密<br>

*用公钥加密

*

*@paramdata

*@paramkey

*@return

*@throwsException

*/

publicstaticbyte[]encryptByPublicKey(byte[]data,Stringkey)

throwsException{

//对公钥解密

byte[]keyBytes=decryptBASE64(key);

//取得公钥

X509EncodedKeySpecx509KeySpec=newX509EncodedKeySpec(keyBytes);

KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);

KeypublicKey=keyFactory.generatePublic(x509KeySpec);

//对数据加密

Ciphercipher=Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.ENCRYPT_MODE,publicKey);

returncipher.doFinal(data);

}

/**

*加密<br>

*用私钥加密

*

*@paramdata

*@paramkey

*@return

*@throwsException

*/

publicstaticbyte[]encryptByPrivateKey(byte[]data,Stringkey)

throwsException{

//对密钥解密

byte[]keyBytes=decryptBASE64(key);

//取得私钥

PKCS8EncodedKeySpecpkcs8KeySpec=newPKCS8EncodedKeySpec(keyBytes);

KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);

KeyprivateKey=keyFactory.generatePrivate(pkcs8KeySpec);

//对数据加密

Ciphercipher=Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.ENCRYPT_MODE,privateKey);

returncipher.doFinal(data);

}

/**

*取得私钥

*

*@paramkeyMap

*@return

*@throwsException

*/

publicstaticStringgetPrivateKey(Map<String,Object>keyMap)

throwsException{

Keykey=(Key)keyMap.get(PRIVATE_KEY);

returnencryptBASE64(key.getEncoded());

}

/**

*取得公钥

*

*@paramkeyMap

*@return

*@throwsException

*/

publicstaticStringgetPublicKey(Map<String,Object>keyMap)

throwsException{

Keykey=(Key)keyMap.get(PUBLIC_KEY);

returnencryptBASE64(key.getEncoded());

}

/**

*初始化密钥

*

*@return

*@throwsException

*/

publicstaticMap<String,Object>initKey()throwsException{

KeyPairGeneratorkeyPairGen=KeyPairGenerator

.getInstance(KEY_ALGORITHM);

keyPairGen.initialize(1024);

KeyPairkeyPair=keyPairGen.generateKeyPair();

//公钥

RSAPublicKeypublicKey=(RSAPublicKey)keyPair.getPublic();

//私钥

RSAPrivateKeyprivateKey=(RSAPrivateKey)keyPair.getPrivate();

Map<String,Object>keyMap=newHashMap<String,Object>(2);

keyMap.put(PUBLIC_KEY,publicKey);

keyMap.put(PRIVATE_KEY,privateKey);

returnkeyMap;

}

}

再给出一个测试类:

Java代码收藏代码

importstaticorg.junit.Assert.*;

importorg.junit.Before;

importorg.junit.Test;

importjava.util.Map;

/**

*

*@author梁栋

*@version1.0

*@since1.0

*/

publicclassRSACoderTest{

privateStringpublicKey;

privateStringprivateKey;

@Before

publicvoidsetUp()throwsException{

Map<String,Object>keyMap=RSACoder.initKey();

publicKey=RSACoder.getPublicKey(keyMap);

privateKey=RSACoder.getPrivateKey(keyMap);

System.err.println("公钥:\n\r"+publicKey);

System.err.println("私钥:\n\r"+privateKey);

}

@Test

publicvoidtest()throwsException{

System.err.println("公钥加密——私钥解密");

StringinputStr="abc";

byte[]data=inputStr.getBytes();

byte[]encodedData=RSACoder.encryptByPublicKey(data,publicKey);

byte[]decodedData=RSACoder.decryptByPrivateKey(encodedData,

privateKey);

StringoutputStr=newString(decodedData);

System.err.println("加密前:"+inputStr+"\n\r"+"解密后:"+outputStr);

assertEquals(inputStr,outputStr);

}

@Test

publicvoidtestSign()throwsException{

System.err.println("私钥加密——公钥解密");

StringinputStr="sign";

byte[]data=inputStr.getBytes();

byte[]encodedData=RSACoder.encryptByPrivateKey(data,privateKey);

byte[]decodedData=RSACoder

.decryptByPublicKey(encodedData,publicKey);

StringoutputStr=newString(decodedData);

System.err.println("加密前:"+inputStr+"\n\r"+"解密后:"+outputStr);

assertEquals(inputStr,outputStr);

System.err.println("私钥签名——公钥验证签名");

//产生签名

Stringsign=RSACoder.sign(encodedData,privateKey);

System.err.println("签名:\r"+sign);

//验证签名

booleanstatus=RSACoder.verify(encodedData,publicKey,sign);

System.err.println("状态:\r"+status);

assertTrue(status);

}

}

控制台输出:

Console代码收藏代码

公钥:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYU/+I0+z1aBl5X6DUUOHQ7FZpmBSDbKTtx89J

EcB64jFCkunELT8qiKly7fzEqD03g8ALlu5XvX+bBqHFy7YPJJP0ekE2X3wjUnh2NxlqpH3/B/xm

1ZdSlCwDIkbijhBVDjA/bu5BObhZqQmDwIxlQInL9oVz+o6FbAZCyHBd7wIDAQAB

私钥:

MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJhT/4jT7PVoGXlfoNRQ4dDsVmmY

FINspO3Hz0kRwHriMUKS6cQtPyqIqXLt/MSoPTeDwAuW7le9f5sGocXLtg8kk/R6QTZffCNSeHY3

GWqkff8H/GbVl1KULAMiRuKOEFUOMD9u7kE5uFmpCYPAjGVAicv2hXP6joVsBkLIcF3vAgMBAAEC

gYBvZHWoZHmS2EZQqKqeuGr58eobG9hcZzWQoJ4nq/CarBAjw/VovUHE490uK3S9ht4FW7Yzg3LV

/MB06Huifh6qf/X9NQA7SeZRRC8gnCQk6JuDIEVJOud5jU+9tyumJakDKodQ3Jf2zQtNr+5ZdEPl

uwWgv9c4kmpjhAdyMuQmYQJBANn6pcgvyYaia52dnu+yBUsGkaFfwXkzFSExIbi0MXTkhEb/ER/D

rLytukkUu5S5ecz/KBa8U4xIslZDYQbLz5ECQQCy5dutt7RsxN4+dxCWn0/1FrkWl2G329Ucewm3

QU9CKu4D+7Kqdj+Ha3lXP8F0Etaaapi7+EfkRUpukn2ItZV/AkEAlk+I0iphxT1rCB0Q5CjWDY5S

Df2B5JmdEG5Y2o0nLXwG2w44OLct/k2uD4cEcuITY5Dvi/4BftMCZwm/dnhEgQJACIktJSnJwxLV

o9dchENPtlsCM9C/Sd2EWpqISSUlmfugZbJBwR5pQ5XeMUqKeXZYpP+HEBj1nS+tMH9u2/IGEwJA

fL8mZiZXan/oBKrblAbplNcKWGRVD/3y65042PAEeghahlJMiYquV5DzZajuuT0wbJ5xQuZB01+X

nfpFpBJ2dw==

公钥加密——私钥解密

加密前:abc

解密后:abc

公钥:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdOj40yEB48XqWxmPILmJAc7UecIN7F32etSHF

9rwbuEh3+iTPOGSxhoSQpOED0vOb0ZIMkBXZSgsxLaBSin2RZ09YKWRjtpCA0kDkiD11gj4tzTiM

l9qq1kwSK7ZkGAgodEn3yIILVmQDuEImHOXFtulvJ71ka07u3LuwUNdB/wIDAQAB

私钥:

MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAN06PjTIQHjxepbGY8guYkBztR5w

g3sXfZ61IcX2vBu4SHf6JM84ZLGGhJCk4QPS85vRkgyQFdlKCzEtoFKKfZFnT1gpZGO2kIDSQOSI

PXWCPi3NOIyX2qrWTBIrtmQYCCh0SffIggtWZAO4QiYc5cW26W8nvWRrTu7cu7BQ10H/AgMBAAEC

gYEAz2JWBizjI31bqhP4XiP9PuY5F3vqBW4T+L9cFbQiyumKJc58yzTWUAUGKIIn3enXLG7dNqGr

mbJro4JeFIJ3CiVDpXR9+FluIgI4SXm7ioGKF2NOMA9LR5Fu82W+pLfpTN2y2SaLYWEDZyp53BxY

j9gUxaxi1MQs+C1ZgDF2xmECQQDy70bQntbRfysP+ppCtd56YRnES1Tyekw0wryS2tr+ivQJl7JF

gp5rPAOXpgrq36xHDwUspQ0sJ0vj0O7ywxr1AkEA6SAaLhrJJrYucC0jxwAhUYyaPN+aOsWymaRh

9jA/Wc0wp29SbGTh5CcMuGpXm1g0M+FKW3dGiHgS3rVUKim4owJAbnxgapUzAgiiHxxMeDaavnHW

9C2GrtjsO7qtZOTgYI/1uT8itvZW8lJTF+9OW8/qXE76fXl7ai9dFnl5kzMk2QJBALfHz/vCsArt

mkRiwY6zApE4Z6tPl1V33ymSVovvUzHnOdD1SKQdD5t+UV/crb3QVi8ED0t2B0u0ZSPfDT/D7kMC

QDpwdj9k2F5aokLHBHUNJPFDAp7a5QMaT64gv/d48ITJ68Co+v5WzLMpzJBYXK6PAtqIhxbuPEc2

I2k1Afmrwyw=

私钥加密——公钥解密

加密前:sign

解密后:sign

私钥签名——公钥验证签名

签名:

ud1RsIwmSC1pN22I4IXteg1VD2FbiehKUfNxgVSHzvQNIK+d20FCkHCqh9djP3h94iWnIUY0ifU+

mbJkhAl/i5krExOE0hknOnPMcEP+lZV1RbJI2zG2YooSp2XDleqrQk5e/QF2Mx0Zxt8Xsg7ucVpn

i3wwbYWs9wSzIf0UjlM=

状态:

true

简要总结一下,使用公钥加密、私钥解密,完成了乙方到甲方的一次数据传递,通过私钥加密、公钥解密,同时通过私钥签名、公钥验证签名,完成了一次甲方到乙方的数据传递与验证,两次数据传递完成一整套的数据交互!

类似数字签名,数字信封是这样描述的:

数字信封

数字信封用加密技术来保证只有特定的收信人才能阅读信的内容。

流程:

信息发送方采用对称密钥来加密信息,然后再用接收方的公钥来加密此对称密钥(这部分称为数字信封),再将它和信息一起发送给接收方;接收方先用相应的私钥打开数字信封,得到对称密钥,然后使用对称密钥再解开信息。

相关推荐