package com.sankuai.meituan.waimai.common; import org.apache.commons.lang.ArrayUtils; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import sun.security.rsa.RSAPrivateKeyImpl; import sun.security.rsa.RSAPublicKeyImpl; import sun.security.util.DerValue; import javax.crypto.Cipher; import java.io.ByteArrayOutputStream; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.util.HashMap; import java.util.Map; /** * Date: 14-9-18 * Time: 下午4:20 */ public class RSAHelper { public static final int ENCODE_MAX = 117; public static final int DECODE_MAX = 128; public static String decode(String encBase64String,String privateKeyString) throws Exception { BASE64Decoder base64Decoder = new BASE64Decoder(); byte[] desEncodeRead = base64Decoder.decodeBuffer(privateKeyString);// DerValue d = new DerValue(desEncodeRead); RSAPrivateKey privateKey= (RSAPrivateKey) RSAPrivateKeyImpl.parseKey(d); Cipher cipher =Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] src = base64Decoder.decodeBuffer(encBase64String); ByteArrayOutputStream out = new ByteArrayOutputStream(); for(int i=0; i<src.length; i+= DECODE_MAX){ byte[] toDecodeSegment = ArrayUtils.subarray(src, i,i+DECODE_MAX); byte[] destByte = cipher.doFinal(toDecodeSegment); System.out.println("decode"+destByte.length); out.write(destByte); } byte[] decode = out.toByteArray(); return new String(decode, "UTF-8"); } public static String encode(String src, String publicKey) throws Exception { BASE64Decoder base64Decoder = new BASE64Decoder(); BASE64Encoder base64Encoder = new BASE64Encoder(); byte[] desEncodeRead = base64Decoder.decodeBuffer(publicKey);// DerValue d = new DerValue(desEncodeRead); RSAPublicKey p = (RSAPublicKey) RSAPublicKeyImpl.parse(d); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, p); ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] toEncode = src.getBytes(); for(int i=0; i<toEncode.length; i+= ENCODE_MAX){ byte[] toEncodeSegment = ArrayUtils.subarray(toEncode, i,i+ENCODE_MAX); byte[] ecodeSegemnt = cipher.doFinal(toEncodeSegment); System.out.println("adfdsSS"+ecodeSegemnt.length); out.write(ecodeSegemnt); } byte[] encode = out.toByteArray(); return base64Encoder.encode(encode); } /** * return map siz KEY为public key value为private key BASE64串 */ public static Map generateRSAKey() throws NoSuchAlgorithmException { BASE64Encoder base64Encoder = new BASE64Encoder(); KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(1024); KeyPair keyPair = keyPairGen.generateKeyPair(); // Generate keys RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); byte[] privateEncode = privateKey.getEncoded(); byte[] publicEncode = publicKey.getEncoded(); String privateKeyBase64 = base64Encoder.encode(privateEncode); String publicKeyBase64 = base64Encoder.encode(publicEncode); Map retValue = new HashMap(1); retValue.put(publicKeyBase64, privateKeyBase64); return retValue; } }
RSA/ECB/PKCS1Padding 算法,加密字节最大117,但不论设置到大,加密后的字节数组大小为128, 解密必须按128个字节一组进行,否则报错,128个字节一组实际上也保证了分段加加密是可逆的,分段 解密后能得到加密前的字节数组