关于解决RSA非对称加密时,将密文存入数据库取出后,再对密文解密的时候抛出javax.crypto.BadPaddingException: Data must start with zero

   RSA非对称加密,由于其对加密的明文长度有限制,所以通常配合对称加密来操作,即把对称加密中的秘钥加密传送来保证用对称加密的安全性。当我用RSA公钥加密AES的 密钥之后,存入mysql之后,然后再取出来进行解密,但是报错javax.crypto.BadPaddingException: Data must start with zero。我改了半天,终于想了一个解决办法,虽然有些麻烦,但是有效果。希望大家多多指教。其实解决思想很简单,就是把加密后的密文放入一个对象中,然后把对象序列化再存入数据库,然后再把对象从数据库取出,再取出其中的密文域的密文。

RSA加密部分:

package com.test;


import java.security.*;
import java.util.ArrayList;

import javax.crypto.*;

public class RSA {
    
 
    private KeyPairGenerator kePaGen=null;                //秘密钥匙生成器;
    private KeyPair          keyPair=null;                //钥匙对,公尺 和米尺;
    private PublicKey        publicKey=null;              //共匙;
    private PrivateKey       privateKey=null;             //密匙;
    private int             keySize    =2048;               //密匙长
    
    public RSA(int keysize) {
        this.keySize= keysize;
        try{
        this.kePaGen= KeyPairGenerator.getInstance("RSA"); //
        this.kePaGen.initialize(this.keySize);   
        //
        this.keyPair=this.kePaGen.genKeyPair();
        this.privateKey=this.keyPair.getPrivate();
        this.publicKey=this.keyPair.getPublic();
         //this.abcharRsaCipher=Cipher.getInstance("RSA/ECB/PKCS1Padding");
        }catch( Exception err){
            err.printStackTrace();
        }
       
    }

    public static String encripyRSA(String platxt,PublicKey publickey)
    {
        String cipherStr=null;                              //返回的加密后的字符串;      
        byte[]plainByte=null;                              //获得明文的byte数组; 
        byte[]cipherByte;                                    //产生秘闻的byte数组;                          
        Cipher cipher =null;
        try{          
        plainByte=platxt.getBytes("ISO-8859-1"); 
        cipher=Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE,publickey); 
        cipherByte=cipher.doFinal(plainByte);        
        cipherStr=new String(cipherByte,"ISO-8859-1"); 
         }catch(Exception err){
            err.printStackTrace();
            System.out.println("error in en: "+err.toString());
        }
        return cipherStr;
    }
    
    public static String decripyRSA(String cphtxt,PrivateKey privateKey)
    {
         byte[] cipherByte =null;                             //获得秘闻的byte数组;        
         byte[] plainByte   =null;                             //解密后的明文数组;
         String   plainStr    =null;                            //解密后的明文数组;
         Cipher   cipher      =null;                            //加密用;
        try{
            cipherByte       =cphtxt.getBytes("ISO-8859-1");    //统一使用该种编码方式;
            cipher =Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE,privateKey);
            plainByte=cipher.doFinal(cipherByte);
            plainStr=new String(plainByte,"ISO-8859-1");         
        }catch(Exception err)
        {
            err.printStackTrace();
        }
        return plainStr;
    }
    
    public PublicKey getPublicKey()
    {
        return this.publicKey;
    }
    public PrivateKey getPrivateKey()
    {
        return this.privateKey;
    }
    
    public static void main(String []args)
    {
    	RSA arsa=new RSA(2048);
    	PublicKey publicKey=arsa.getPublicKey();
    	System.out.println(publicKey);
        String en=RSA.encripyRSA("101",publicKey);      
        PrivateKey privateKey=arsa.getPrivateKey();
        System.out.println(privateKey);
           
        
        Dao dao=new Daoimpl();
        CC cc=new CC(en);//将密文存入一个对象
        dao.addObject(cc);//将对象存入数据库
        ArrayList<CC> list=dao.queryCC();//从数据库中获取存入的对象
        String cString=null;
		cString =list.get(0).cString;//将对象中的密文取出
		
        System.out.println("cString: "+cString);
        String de=RSA.decripyRSA(cString,privateKey);//现在用从数据库取出的密文就可以成功解密,就不会出现这个异常,javax.crypto.BadPaddingException: Data must start with zero
        System.out.println(de);
        dao.close();
  
    }
}

数据库操作部分:

package com.test;

import java.math.BigInteger;
import java.util.ArrayList;

public interface Dao {

	public abstract int queryRecordsCount();
	public abstract boolean addObject(CC cc);
	public abstract ArrayList<CC> queryObject();
	public abstract void close();
}

package com.test;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.math.BigInteger;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

public class Daoimpl implements Dao {

	private Connection connection;
	private ResultSet rs;
    PreparedStatement pst ;
	public Daoimpl(){
		connection=DBOperations.getConnection();
	}
	@Override
	public boolean addObject(CC cc) {
		// TODO Auto-generated method stub
		boolean result=false;
		int i=0;
		 String sql="insert into test(c) values(?)"; 
			try {
				pst = connection.prepareStatement(sql);      
				pst.setObject(1, cc);
				i = pst.executeUpdate();  
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			         //执行插入数据操作,返回影响的行数
			 if (i == 1) {
			     result = true;
			 }
			 return result;

	}
	@Override
	public ArrayList<CC> queryObject() {
		// TODO Auto-generated method stub
		
        ArrayList<CC> result=new ArrayList<>();
        String sql="select * from test";
        try
        {
            pst = connection.prepareStatement(sql);
            rs = pst.executeQuery();
            int i=0;
            while(rs.next())
            {
                Blob inBlob=rs.getBlob(2);                             //获取blob对象  
                
                InputStream is=inBlob.getBinaryStream();                //获取二进制流对象  
                BufferedInputStream bis=new BufferedInputStream(is);
                
                byte[] buff=new byte[(int) inBlob.length()];  
                while(-1!=(bis.read(buff, 0, buff.length))){            //一次性全部读到buff中  
                    ObjectInputStream in=new ObjectInputStream(new ByteArrayInputStream(buff));  
                    CC p=(CC)in.readObject();                   //读出对象  
                      
                    result.add(p);  
                } 
                
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return result;
 
	}
	
	
	@Override
	public int queryRecordsCount() {
	        int result = 0;
	        String sql="select count(*) from test";
	        try
	        {
	            pst = connection.prepareStatement(sql);
	            rs = pst.executeQuery();
	            if (rs.next())
	            {
	                result = rs.getInt(1);
	            }
	        }
	        catch (Exception e)
	        {
	            e.printStackTrace();
	        }
	        return result;
	}
	
	@Override
	public void close() {
		// TODO Auto-generated method stub
		DBOperations.freeResource(connection, pst, rs);
	}
	

}

序列化的对象:

package com.test;

import java.io.Serializable;

public class CC implements Serializable {

	public String cString;

	public CC(String cString) {
		super();
		this.cString = cString;
	}
	
	
}


最后是数据库的字段表:


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值