RSA加密/解密 Decryption error异常解决

RSA加密/解密 Decryption error异常解决

import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;

public class RSATest {

    private static final String ALGORITHM = "RSA";
    private static final String PUBLICK_EY = "PUBLICK_EY";
    private static final String PRIVATE_KEY = "PRIVATE_KEY";
    /**
     * 加密算法
     */
    private static final String CIPHER_DE = "RSA";
    /**
     * 解密算法
     */
    private static final String CIPHER_EN = "RSA";
    /**
     * 密钥长度
     */
    private static final Integer KEY_LENGTH = 1024;

    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;

    /**
     * 生成秘钥对,公钥和私钥
     *
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static Map<String, Object> genKeyPair() throws NoSuchAlgorithmException {
        Map<String, Object> keyMap = new HashMap<String, Object>();
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
        keyPairGenerator.initialize(KEY_LENGTH); // 秘钥字节数
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();
        keyMap.put(PUBLICK_EY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }

    /**
     * 公钥加密
     *
     * @param data
     * @param publicKey
     * @return
     * @throws InvalidKeySpecException
     */
    public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
        // 得到公钥
        byte[] keyBytes = Base64.decodeBase64(publicKey.getBytes());
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        Key key = keyFactory.generatePublic(x509EncodedKeySpec);
        // 加密数据,分段加密  
        Cipher cipher = Cipher.getInstance(CIPHER_EN);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        int inputLength = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        while (inputLength - offset > 0) {
            if (inputLength - offset > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offset, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offset, inputLength - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return encryptedData;
    }

    /**
     * 私钥解密
     *
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] data, String privateKey) throws Exception {
        // 得到私钥  
        byte[] keyBytes = Base64.decodeBase64(privateKey.getBytes());
        PKCS8EncodedKeySpec pKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        Key key = keyFactory.generatePrivate(pKCS8EncodedKeySpec);
        // 解密数据,分段解密
        Cipher cipher = Cipher.getInstance(CIPHER_DE);
        cipher.init(Cipher.DECRYPT_MODE, key);
        int inputLength = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        byte[] tmp;
        while (inputLength - offset > 0) {
            if (inputLength - offset > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(data, offset, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offset, inputLength - offset);
            }
//            out.write(cache, 0, cache.length);
            out.write(cache);
            i++;
            offset = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return decryptedData;
    }

    /**
     * 获取公钥
     *
     * @param keyMap
     * @return
     */
    public static String getPublicKey(Map<String, Object> keyMap) {
        Key key = (Key) keyMap.get(PUBLICK_EY);
        String str = new String(Base64.encodeBase64(key.getEncoded()));
        return str;
    }

    /**
     * 获取私钥
     *
     * @param keyMap
     * @return
     */
    public static String getPrivateKey(Map<String, Object> keyMap) {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        String str = new String(Base64.encodeBase64(key.getEncoded()));
        return str;
    }

    public static void main(String[] args) throws Exception {
        Map<String, Object> keyMap = RSATest.genKeyPair();
        String publicKey = RSATest.getPublicKey(keyMap);
        String privateKey = RSATest.getPrivateKey(keyMap);
        System.out.println("公钥:" + publicKey);
        System.out.println("私钥:" + privateKey);
        // 公钥加密  
        String sourceStr = "<REQ><HEAD><ReqCode>WDISReqCode><MsgNo>500MsgNo><MsgId>20171113123408MsgId><MsgRef>20171113123408MsgRef><Teller>00000951Teller><BchCde>800000000BchCde><WorkDate>20171113WorkDate><WorkTime>123408WorkTime>HEAD><MSG><ApplSeq>1666645ApplSeq><AppAdvice>同意AppAdvice><AppConclusion>10AppConclusion><ApptList><Result><ApptTyp>01ApptTyp><CustName>林羽凡CustName><IdTyp>20IdTyp><IdNo>350521196211216597IdNo><ApptStartDate>1962-11-21ApptStartDate><ApptAge>55ApptAge><CrtBch>800000001CrtBch><CrtDt>2017-11-13CrtDt><IndivInfo><IndivSex>10IndivSex><IndivMarital>20IndivMarital><IndivEdu>10IndivEdu><IndivDegree>4IndivDegree><RegProvince>110000RegProvince><RegCity>110100RegCity><LiveInfo>10LiveInfo><LiveProvince>110000LiveProvince><LiveCity>110100LiveCity><LiveArea>110105LiveArea><LiveAddr>北京市市辖区朝阳区xxxxxxxLiveAddr><LiveZip>100000LiveZip><LiveMj>299.66LiveMj><LocalResid>10LocalResid><IndivMobile>13522015858IndivMobile><PositionOpt>10PositionOpt><IndivEmpName>山东科技有限公司IndivEmpName><IndivEmpTyp>ZIndivEmpTyp><IndivMthInc>500000.0IndivMthInc><MailOpt>AMailOpt><MailProvince>110000MailProvince><MailCity>110100MailCity><MailArea>110105MailArea><MailAddr>北京市市辖区朝阳区xxxxxxxMailAddr><IndivProfsn>00IndivProfsn><IndivIndtryPaper>QIndivIndtryPaper><IndivPro>1IndivPro><PptyLive>YPptyLive>IndivInfo><ExtInfo><SpouseName>黄海涛SpouseName><SpouseIdTyp>20SpouseIdTyp><SpouseIdNo>110105198310200112SpouseIdNo><SpouseMobile>13589565487SpouseMobile>ExtInfo><RelList><Result><RelName>黄海涛RelName><RelMobile>13589565487RelMobile><RelRelation>06RelRelation>Result><Result/>RelList>Result><Result><ApptRelation>06ApptRelation><ApptTyp>02ApptTyp><CustName>黄海涛CustName><IdTyp>20IdTyp><IdNo>110105198310200112IdNo><ApptStartDate>1983-10-20ApptStartDate><ApptAge>34ApptAge><CrtBch>800000001CrtBch><CrtDt>2017-11-13CrtDt><IndivInfo><IndivSex>20IndivSex><IndivMarital>20IndivMarital><IndivDegree>0IndivDegree><LiveAddr>北京市市辖区朝阳区xxxxxxxLiveAddr><LiveMj>299.66LiveMj><LocalResid>10LocalResid><IndivMobile>13581829258IndivMobile><PositionOpt>50PositionOpt><IndivEmpName>个体IndivEmpName><IndivEmpTyp>ZIndivEmpTyp><MailOpt>AMailOpt><MailAddr>北京市市辖区朝阳区xxxxxxxMailAddr><PptyLive>YPptyLive>IndivInfo><ExtInfo><SpouseName>林羽凡SpouseName><SpouseIdTyp>20SpouseIdTyp><SpouseIdNo>350521196211216597SpouseIdNo><SpouseMobile>135xxxxxxxxSpouseMobile>ExtInfo><RelList><Result><RelName>黄海涛RelName><RelMobile>135xxxxxxxxRelMobile><RelRelation>06RelRelation>Result>RelList>Result>ApptList><HouInfo><Location>朝阳区xxxxxLocation><HouseArea>299.66HouseArea><CompDate>2009-01-01CompDate><PropRight>12PropRight><HouseKindList>01HouseKindList><HouseClass>01HouseClass><HouseType>09HouseType><HouseFrameSign>99HouseFrameSign><HouseCertKind>03HouseCertKind><PptyProvince>110000PptyProvince><PptyCity>110100PptyCity><PptyArea>110105PptyArea><PptyAddr>朝阳区xxxxxPptyAddr><OwnerName>林羽凡OwnerName><HouseCertNo>北京房权证朝字第907946号HouseCertNo>HouInfo><GurtInfo><gurtAmt>2.0E7gurtAmt><collateralValue>2.0E7collateralValue><gurtStartDt>2017-11-02gurtStartDt><gurtEndDt>2020-11-02gurtEndDt><gurtSignDt>2017-11-02gurtSignDt><collInd>YcollInd><regSts>02regSts><mortgagorTyp>01mortgagorTyp><rightCertTyp>01rightCertTyp><rightCertNo>京(2017)朝不动产证明第0075996号rightCertNo><custName>林羽凡custName><mortgageType>01mortgageType><isRent>NisRent><obligorName>林羽凡obligorName>GurtInfo><ApplInfo><ApplCde>201711131200000131495ApplCde><ApplSeq>1666645ApplSeq><IdTyp>20IdTyp><IdNo>350521196211216597IdNo><CustName>林羽凡CustName><ProPurAmt>2.0E7ProPurAmt><Purpose>OTHPurpose><AppOrigin>03AppOrigin><DocChannel>SYS001DocChannel><ApplyDt>2017-10-27ApplyDt><FstPct>0FstPct><FstPay>0FstPay><ApplyAmt>2.0E7ApplyAmt><ApprvAmt>2.0E7ApprvAmt><ApplyTnr>36ApplyTnr><ApplyTnrTyp>MApplyTnrTyp><ApprvTnr>36ApprvTnr><ApprvTnrTyp>MApprvTnrTyp><LoanTyp>ZYYH002LoanTyp><MtdCde>LM004MtdCde><LoanFreq>1MLoanFreq><MtdMode>RVMtdMode><PriceIntRat>0.07799998999999999PriceIntRat><CrtDt>2017-11-02CrtDt><TypGrp>04TypGrp><GutrOpt>20GutrOpt><CrtBch>800000001CrtBch><CrtBchInd>NCrtBchInd><RepcOpt>NYFRepcOpt><DueDayOpt>2DueDayOpt><DueDay>21DueDay><Form>04Form>ApplInfo><MtdList><Result><MtdCde>LM004MtdCde><MtdTyp>04MtdTyp><LoanInstal>36LoanInstal><ApplMtdRateTyp>1ApplMtdRateTyp><ApplMtdRateFloat>64.2105ApplMtdRateFloat>Result>MtdList><AcctList><Result><ApplAcKind>01ApplAcKind><ApplAcTyp>01ApplAcTyp><RpymAcBank>105100000017RpymAcBank><RpymAcNam>于三RpymAcNam><RpymAcNo>6217000010039470748RpymAcNo><RpymIdTyp>20RpymIdTyp><RpymMethod>1RpymMethod>Result><Result><ApplAcKind>02ApplAcKind><ApplAcTyp>01ApplAcTyp><RpymAcBank>105100000017RpymAcBank><RpymAcNam>林羽凡RpymAcNam><RpymAcNo>5522450010194467RpymAcNo><RpymIdTyp>20RpymIdTyp><RpymIdNo>350521196211216597RpymIdNo><RpymMethod>1RpymMethod>Result>AcctList>MSG>REQ>";
        System.out.println("加密前:" + sourceStr);
        byte[] encryptStrByte = RSATest.encryptByPublicKey(sourceStr.getBytes(), publicKey);
        byte[] btt = Base64.encodeBase64(encryptStrByte);
        String encryptStr = new String(btt);
        System.out.println("加密后:" + encryptStr);
        System.out.println("长度:" + encryptStr.length());
        // 私钥解密  
        byte[] decryptStrByte = RSATest.decryptByPrivateKey(Base64.decodeBase64(Base64.encodeBase64(encryptStrByte)), privateKey);
        String sourceStr_1 = new String(decryptStrByte);
        System.out.println("解密后:" + sourceStr_1);
    }
}  

密钥长度修改为2048位时,报以下错误:

Exception in thread "main" javax.crypto.BadPaddingException: Decryption error
    at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
    at sun.security.rsa.RSAPadding.unpad(Unknown Source)
    at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
    at javax.crypto.Cipher.doFinal(Cipher.java:2223)
    at com.caxs.esign.util.MYtest.decryptByPrivateKey(MYtest.java:117)
    at com.caxs.esign.util.MYtest.main(MYtest.java:175)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

这是由于最大解密长度不正确导致报错,MAX_DECRYPT_BLOCK应等于密钥长度/8(1byte=8bit),所以当密钥位数为2048时,最大解密长度应为256.

private static final int MAX_DECRYPT_BLOCK = 128;

你可能感兴趣的:(rsa)