RSA加解密算法java实现(已添加分段加密算法处理)

一 RSA简介

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

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

二 数字签名技术

数字签名技术是将摘要信息用发送者的私钥加密,与原文一起传送给接收者。接收者只有用发送者的公钥才能解密被加密的摘要信息,然后用HASH函数对收到的原文产生一个摘要信息,与解密的摘要信息对比。如果相同,则说明收到的信息是完整的,在传输过程中没有被修改,否则说明信息被修改过,因此数字签名能够验证信息的完整性。

数字签名是个加密的过程,数字签名验证是个解密的过程。

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

       流程图如下图所示:

注:如果要建立更安全的加密消息传递模型,需要消息发送方和消息接收方各构建一套密钥对,并分别将各自的公钥暴露给对方,在进行消息传递时,A通过B的公钥对数据加密,B接收到消息通过B的私钥进行解密,反之,B通过A的公钥进行加密,A接收到消息后通过A的私钥进行解密。


4、 一般我认为RSA加解密共有两种方案,一种是通信双方共用一套公私密钥(公钥双方共有,私钥发送者保持);一种是通信双方一人一套公司密钥(通信时互换双方的公钥,安全性比较高)。显然第一种方式安全性低一些,并且复杂度低;第二种方式安全性高,但是复杂度高。

RSA加解密算法还有两种不同的方式,一种是使用对称密钥(比如DES等加解密方法)加密数据,然后使用非对称密钥(RSA加解密密钥)加密对称密钥;另一种是直接使用非对称密钥加密数据。第一种方式安全性高,复杂度也高,不存在加密数据长度限制问题,第二种方式安全性差一些,复杂度低,但是存在加密数据限制问题(即使用非对称密钥加密数据时,一次加密的数据长度是(密钥长度/8-11))。

因为公司业务功能需求限制,我下面展示的是双方采用一套公私密钥,并且采用公司密钥加解密数据的方法,其中还添加了对数据分段加密的方法。

5、实际代码实现

RSA_Encrypt类

主要就是包涵:加密方法、解密方法、生成密钥对方法、生成签名方法、验证签名方法

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
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.SecureRandom;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;


import javax.crypto.Cipher;


import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;


public class RSA_Encrypt {
/** 指定加密算法为RSA */
private static String ALGORITHM = "RSA";
/** 指定key的大小 */
private static int KEYSIZE = 1024;
/** 指定公钥存放文件 */
private static String PUBLIC_KEY_FILE = "PublicKey";
/** 指定私钥存放文件 */
private static String PRIVATE_KEY_FILE = "PrivateKey";
 
public static final String KEY_ALGORITHM = "RSA";   
public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; 
/**
* 生成密钥对
*/
public static void generateKeyPair() throws Exception {
/** RSA算法要求有一个可信任的随机数源 */
SecureRandom sr = new SecureRandom();
/** 为RSA算法创建一个KeyPairGenerator对象 */
KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);
/** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */
kpg.initialize(KEYSIZE, sr);
/** 生成密匙对 */
KeyPair kp = kpg.generateKeyPair();
/** 得到公钥 */
Key publicKey = kp.getPublic();
/** 得到私钥 */
Key privateKey = kp.getPrivate();
/** 用对象流将生成的密钥写入文件 */
ObjectOutputStream oos1 = new ObjectOutputStream(new FileOutputStream(PUBLIC_KEY_FILE));
ObjectOutputStream oos2 = new ObjectOutputStream(new FileOutputStream(PRIVATE_KEY_FILE));
oos1.writeObject(publicKey);
oos2.writeObject(privateKey);
/** 清空缓存,关闭文件输出流 */
oos1.close();
oos2.close();
}


/**
    * 产生签名
    * @param data
    * @param privateKey
    * @return
    * @throws Exception
    */
   public static String sign(byte[] data, String privateKey) throws Exception {   
       // 解密由base64编码的私钥   
       byte[] keyBytes = decryptBASE64(privateKey);   
 
       // 构造PKCS8EncodedKeySpec对象   
       PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);   
 
       // KEY_ALGORITHM 指定的加密算法   
       KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);   
 
       // 取私钥对象   
       PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);   
 
       // 用私钥对信息生成数字签名   
       Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);   
       signature.initSign(priKey);   
       signature.update(data);   
 
       return encryptBASE64(signature.sign());   
   } 


   /**
    * 验证签名
    * @param data
    * @param publicKey
    * @param sign
    * @return
    * @throws Exception
    */
   public static boolean verify(byte[] data, String publicKey, String sign)   
           throws Exception {   
 
       // 解密由base64编码的公钥   
       byte[] keyBytes = decryptBASE64(publicKey);   
 
       // 构造X509EncodedKeySpec对象   
       X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);   
 
       // KEY_ALGORITHM 指定的加密算法   
       KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);   
 
       // 取公钥匙对象   
       PublicKey pubKey = keyFactory.generatePublic(keySpec);   
 
       Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);   
       signature.initVerify(pubKey);   
       signature.update(data);   
 
       // 验证签名是否正常   
       return signature.verify(decryptBASE64(sign));   
   } 
   
   
   /**
    * BASE64解密
    * @param key
    * @return
    * @throws Exception
    */
   public static byte[] decryptBASE64(String key) throws Exception{
       return (new BASE64Decoder()).decodeBuffer(key);
   }
   
   /**
    * BASE64加密
    * @param key
    * @return
    * @throws Exception
    */
   public static String encryptBASE64(byte[] key)throws Exception{
       return (new BASE64Encoder()).encodeBuffer(key);
   }
   
   /**
* 加密方法 source: 源数据
*/
public static String encrypt(String source) throws Exception {
//generateKeyPair();
/** 将文件中的公钥对象读出 */
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
Key key = (Key) ois.readObject();
ois.close();
/** 得到Cipher对象来实现对源数据的RSA加密 */
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
int MaxBlockSize = KEYSIZE / 8 ;    
String[] datas = splitString(source, MaxBlockSize - 11);
String mi = "";
for (String s : datas) {  
mi += bcd2Str(cipher.doFinal(s.getBytes()));  
}
return mi;

}
 
/** 
*/  
public static String[] splitString(String string, int len) {  
int x = string.length() / len;  
int y = string.length() % len;  
int z = 0;  
if (y != 0) {  
z = 1;  
}  
String[] strings = new String[x + z];  
String str = "";  
for (int i=0; i<x+z; i++) {  
if (i==x+z-1 && y!=0) {  
str = string.substring(i*len, i*len+y);  
}else{  
str = string.substring(i*len, i*len+len);  
}  
strings[i] = str;  
}  
return strings;  
} 

/** 
*/  
public static String bcd2Str(byte[] bytes) {  
char temp[] = new char[bytes.length * 2], val;  


for (int i = 0; i < bytes.length; i++) {  
val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);  
temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');  


val = (char) (bytes[i] & 0x0f);  
temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');  
}  
return new String(temp);  
}  

/**
* 解密算法 cryptograph:密文
*/
public static String decrypt(String cryptograph) throws Exception {
/** 将文件中的私钥对象读出 */
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
Key key = (Key) ois.readObject();
/** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
int key_len = KEYSIZE / 8 ; 
byte[] bytes = cryptograph.getBytes();  
byte[] bcd = ASCII_To_BCD(bytes, bytes.length); 
System.err.println(bcd.length);  
String ming = "";  
byte[][] arrays = splitArray(bcd, key_len);  
for(byte[] arr : arrays){  
ming += new String(cipher.doFinal(arr));  
}  
return ming;  
}
 
/** 
*  
*/  
public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {  
byte[] bcd = new byte[asc_len / 2];  
int j = 0;  
for (int i = 0; i < (asc_len + 1) / 2; i++) {  
bcd[i] = asc_to_bcd(ascii[j++]);  
bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));  
}  
return bcd;  
} 

public static byte asc_to_bcd(byte asc) {  
byte bcd;  


if ((asc >= '0') && (asc <= '9'))  
bcd = (byte) (asc - '0');  
else if ((asc >= 'A') && (asc <= 'F'))  
bcd = (byte) (asc - 'A' + 10);  
else if ((asc >= 'a') && (asc <= 'f'))  
bcd = (byte) (asc - 'a' + 10);  
else  
bcd = (byte) (asc - 48);  
return bcd;  
}  

/** 
*/  
public static byte[][] splitArray(byte[] data,int len){  
int x = data.length / len;  
int y = data.length % len;  
int z = 0;  
if(y!=0){  
z = 1;  
}  
byte[][] arrays = new byte[x+z][];  
byte[] arr;  
for(int i=0; i<x+z; i++){  
arr = new byte[len];  
if(i==x+z-1 && y!=0){  
System.arraycopy(data, i*len, arr, 0, y);  
}else{  
System.arraycopy(data, i*len, arr, 0, len);  
}  
arrays[i] = arr;  
}  
return arrays;  
} 

public static String getpublickey() throws Exception{
/** 将文件中的公钥对象读出 */
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
Key key = (Key) ois.readObject();
String publickey=encryptBASE64(key.getEncoded());
return publickey;
}

public static String getprivatekey() throws Exception{
/** 将文件中的私钥对象读出 */
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
Key key = (Key) ois.readObject();
String privatekey=encryptBASE64(key.getEncoded());
return privatekey;
}
}

Test2_Main类,这是一个测试类

public class Test2_Main {

publicstaticvoid main(String[] args)throws Exception {
RSA_Encrypt.generateKeyPair();
String source ="Hello World!";// 要加密的字符串
String cryptograph = RSA_Encrypt.encrypt(source);// 生成的密文
String target = RSA_Encrypt.decrypt(cryptograph);// 解密密文
System.out.println("解密之后的明文是:"+target);
byte[]bytes =source.getBytes();  
// 产生签名   
        String sign = RSA_Encrypt.sign(bytes, RSA_Encrypt.getprivatekey());   
        System.err.println("签名:" +sign);   
  
        // 验证签名   
        boolean status = RSA_Encrypt.verify(bytes, RSA_Encrypt.getpublickey(),sign);   
        System.err.println("状态:" +status);  
 
}
}

以上就是根据查找的资料,我自己整理的关于RSA加解密算法java代码实现。




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值