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个字节一组实际上也保证了分段加加密是可逆的,分段
解密后能得到加密前的字节数组