您的位置:首页 > 编程语言 > Java开发

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

2017-06-14 09:10 736 查看
   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;
}

}


最后是数据库的字段表:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐