1. 程式人生 > >RSA加密/解密 Decryption error異常解決

RSA加密/解密 Decryption error異常解決

公司 engine ued pap source purpose pro location uri

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>WDIS</ReqCode><MsgNo>500</MsgNo><MsgId>20171113123408</MsgId><MsgRef>20171113123408</MsgRef><Teller>00000951</Teller><BchCde>800000000</BchCde><WorkDate>20171113</WorkDate><WorkTime>123408</WorkTime></HEAD><MSG><ApplSeq>1666645</ApplSeq><AppAdvice>同意</AppAdvice><AppConclusion>10</AppConclusion><ApptList><Result><ApptTyp>01</ApptTyp><CustName>林羽凡</CustName><IdTyp>20</IdTyp><IdNo>350521196211216597</IdNo><ApptStartDate>1962-11-21</ApptStartDate><ApptAge>55</ApptAge><CrtBch>800000001</CrtBch><CrtDt>2017-11-13</CrtDt><IndivInfo><IndivSex>10</IndivSex><IndivMarital>20</IndivMarital><IndivEdu>10</IndivEdu><IndivDegree>4</IndivDegree><RegProvince>110000</RegProvince><RegCity>110100</RegCity><LiveInfo>10</LiveInfo><LiveProvince>110000</LiveProvince><LiveCity>110100</LiveCity><LiveArea>110105</LiveArea><LiveAddr>北京市市轄區朝陽區xxxxxxx</LiveAddr><LiveZip>100000</LiveZip><LiveMj>299.66</LiveMj><LocalResid>10</LocalResid><IndivMobile>13522015858</IndivMobile><PositionOpt>10</PositionOpt><IndivEmpName>山東科技有限公司</IndivEmpName><IndivEmpTyp>Z</IndivEmpTyp><IndivMthInc>500000.0</IndivMthInc><MailOpt>A</MailOpt><MailProvince>110000</MailProvince><MailCity>110100</MailCity><MailArea>110105</MailArea><MailAddr>北京市市轄區朝陽區xxxxxxx</MailAddr><IndivProfsn>00</IndivProfsn><IndivIndtryPaper>Q</IndivIndtryPaper><IndivPro>1</IndivPro><PptyLive>Y</PptyLive></IndivInfo><ExtInfo><SpouseName>黃海濤</SpouseName><SpouseIdTyp>20</SpouseIdTyp><SpouseIdNo>110105198310200112</SpouseIdNo><SpouseMobile>13589565487</SpouseMobile></ExtInfo><RelList><Result><RelName>黃海濤</RelName><RelMobile>13589565487</RelMobile><RelRelation>06</RelRelation></Result><Result/></RelList></Result><Result><ApptRelation>06</ApptRelation><ApptTyp>02</ApptTyp><CustName>黃海濤</CustName><IdTyp>20</IdTyp><IdNo>110105198310200112</IdNo><ApptStartDate>1983-10-20</ApptStartDate><ApptAge>34</ApptAge><CrtBch>800000001</CrtBch><CrtDt>2017-11-13</CrtDt><IndivInfo><IndivSex>20</IndivSex><IndivMarital>20</IndivMarital><IndivDegree>0</IndivDegree><LiveAddr>北京市市轄區朝陽區xxxxxxx</LiveAddr><LiveMj>299.66</LiveMj><LocalResid>10</LocalResid><IndivMobile>13581829258</IndivMobile><PositionOpt>50</PositionOpt><IndivEmpName>個體</IndivEmpName><IndivEmpTyp>Z</IndivEmpTyp><MailOpt>A</MailOpt><MailAddr>北京市市轄區朝陽區xxxxxxx</MailAddr><PptyLive>Y</PptyLive></IndivInfo><ExtInfo><SpouseName>林羽凡</SpouseName><SpouseIdTyp>20</SpouseIdTyp><SpouseIdNo>350521196211216597</SpouseIdNo><SpouseMobile>135xxxxxxxx</SpouseMobile></ExtInfo><RelList><Result><RelName>黃海濤</RelName><RelMobile>135xxxxxxxx</RelMobile><RelRelation>06</RelRelation></Result></RelList></Result></ApptList><HouInfo><Location>朝陽區xxxxx</Location><HouseArea>299.66</HouseArea><CompDate>2009-01-01</CompDate><PropRight>12</PropRight><HouseKindList>01</HouseKindList><HouseClass>01</HouseClass><HouseType>09</HouseType><HouseFrameSign>99</HouseFrameSign><HouseCertKind>03</HouseCertKind><PptyProvince>110000</PptyProvince><PptyCity>110100</PptyCity><PptyArea>110105</PptyArea><PptyAddr>朝陽區xxxxx</PptyAddr><OwnerName>林羽凡</OwnerName><HouseCertNo>北京房權證朝字第907946號</HouseCertNo></HouInfo><GurtInfo><gurtAmt>2.0E7</gurtAmt><collateralValue>2.0E7</collateralValue><gurtStartDt>2017-11-02</gurtStartDt><gurtEndDt>2020-11-02</gurtEndDt><gurtSignDt>2017-11-02</gurtSignDt><collInd>Y</collInd><regSts>02</regSts><mortgagorTyp>01</mortgagorTyp><rightCertTyp>01</rightCertTyp><rightCertNo>京(2017)朝不動產證明第0075996號</rightCertNo><custName>林羽凡</custName><mortgageType>01</mortgageType><isRent>N</isRent><obligorName>林羽凡</obligorName></GurtInfo><ApplInfo><ApplCde>201711131200000131495</ApplCde><ApplSeq>1666645</ApplSeq><IdTyp>20</IdTyp><IdNo>350521196211216597</IdNo><CustName>林羽凡</CustName><ProPurAmt>2.0E7</ProPurAmt><Purpose>OTH</Purpose><AppOrigin>03</AppOrigin><DocChannel>SYS001</DocChannel><ApplyDt>2017-10-27</ApplyDt><FstPct>0</FstPct><FstPay>0</FstPay><ApplyAmt>2.0E7</ApplyAmt><ApprvAmt>2.0E7</ApprvAmt><ApplyTnr>36</ApplyTnr><ApplyTnrTyp>M</ApplyTnrTyp><ApprvTnr>36</ApprvTnr><ApprvTnrTyp>M</ApprvTnrTyp><LoanTyp>ZYYH002</LoanTyp><MtdCde>LM004</MtdCde><LoanFreq>1M</LoanFreq><MtdMode>RV</MtdMode><PriceIntRat>0.07799998999999999</PriceIntRat><CrtDt>2017-11-02</CrtDt><TypGrp>04</TypGrp><GutrOpt>20</GutrOpt><CrtBch>800000001</CrtBch><CrtBchInd>N</CrtBchInd><RepcOpt>NYF</RepcOpt><DueDayOpt>2</DueDayOpt><DueDay>21</DueDay><Form>04</Form></ApplInfo><MtdList><Result><MtdCde>LM004</MtdCde><MtdTyp>04</MtdTyp><LoanInstal>36</LoanInstal><ApplMtdRateTyp>1</ApplMtdRateTyp><ApplMtdRateFloat>64.2105</ApplMtdRateFloat></Result></MtdList><AcctList><Result><ApplAcKind>01</ApplAcKind><ApplAcTyp>01</ApplAcTyp><RpymAcBank>105100000017</RpymAcBank><RpymAcNam>於三</RpymAcNam><RpymAcNo>6217000010039470748</RpymAcNo><RpymIdTyp>20</RpymIdTyp><RpymMethod>1</RpymMethod></Result><Result><ApplAcKind>02</ApplAcKind><ApplAcTyp>01</ApplAcTyp><RpymAcBank>105100000017</RpymAcBank><RpymAcNam>林羽凡</RpymAcNam><RpymAcNo>5522450010194467</RpymAcNo><RpymIdTyp>20</RpymIdTyp><RpymIdNo>350521196211216597</RpymIdNo><RpymMethod>1</RpymMethod></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加密/解密 Decryption error異常解決