加密使用的是公钥对数据进行加密,而且当你使用一把1024bit的rsa公钥的时候,你一次只能加密最多117byte的数据,如果数据量超过这个数,可能会涉及到对数据进行分段加密的问题。而且现在rsa 1024bit长度的钥匙已经被证明了不够安全,应该尽量使用2048bit长度的钥匙。2048bit长度的钥匙一次可以加密245byte长度的数据。这个计算方法是 2048bit/8 = 256byte - 11byte = 245byte长数据。就是钥匙长度减去11byte得到的自己最大能一次加密多长的数据。如果超过了就会报错,所以很多平台要求对数据用公钥进行加密,就可能涉及到分段加密的问题。同时要注意的是,解密的时候不存在这11byte的减少。就是说一把1024bit的钥匙可以解密128byte长的数据而2048bit的可以解密256byte的数据。
RSA非对称加密内容长度有限制,1024位key的最多只能加密117位数据,否则就会报错(javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes)
解决办法是用对称加密(AES/DES etc)加密数据,然后用RSA公钥加密对称加密的密钥,用RSA的私钥解密得到对称加密的密钥,然后完成反向操作得到明文。

from Crypto import Random 
#from Crypto.Hash import SHA 
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5 
#from Crypto.Signature import PKCS1_v1_5 as Signature_pkcs1_v1_5 
from Crypto.PublicKey import RSA 
import base64 
 
#伪随机数生成器 
random_generator = Random.new().read 
# rsa算法生成实例 
rsa = RSA.generate(2048, random_generator) 
 
# master的秘钥对的生成 
private_pem = rsa.exportKey() 
 
with open('master-private.pem', 'wb+') as f: 
    f.write(private_pem) 
 
public_pem = rsa.publickey().exportKey() 
with open('master-public.pem', 'wb') as f: 
 f.write(public_pem) 
 
# ghost的秘钥对的生成 
private_pem = rsa.exportKey() 
with open('master-private.pem', 'wb') as f: 
 f.write(private_pem) 
 
public_pem = rsa.publickey().exportKey() 
with open('master-public.pem', 'wb') as f: 
 f.write(public_pem) 
 
 
 
message = 'hello ghost, this is a plian text' 
cipher_text ='' 
with open('master-public.pem', 'rb+') as f: 
    key = f.read() 
    rsakey = RSA.importKey(key) 
    cipher = Cipher_pkcs1_v1_5.new(rsakey) 
    cipher_text = base64.b64encode(cipher.encrypt(bytes(message,"utf-8"))) 
    print(cipher_text) 
 
text='' 
with open('master-private.pem', 'rb+') as f: 
    key = f.read() 
    rsakey = RSA.importKey(key) 
    cipher = Cipher_pkcs1_v1_5.new(rsakey) 
    text = str(cipher.decrypt(base64.b64decode(cipher_text), random_generator),"utf-8") 
    print(text) 
 
 
assert text == message, 'decrypt falied'

java版分段加密

import java.io.ByteArrayOutputStream; 
import java.io.UnsupportedEncodingException; 
import java.net.URLEncoder; 
import java.security.Key; 
import java.security.KeyFactory; 
import java.security.KeyPair; 
import java.security.KeyPairGenerator; 
import java.security.MessageDigest; 
import java.security.PrivateKey; 
import java.security.PublicKey; 
import java.security.Signature; 
import java.security.interfaces.RSAPrivateKey; 
import java.security.interfaces.RSAPublicKey; 
import java.security.spec.PKCS8EncodedKeySpec; 
import java.security.spec.X509EncodedKeySpec; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.Comparator; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
 
import javax.crypto.Cipher; 
    
	private static final String EQUAL_FLAG = "="; 
	private static final String APPEND_FLAG = "&"; 
	/**  
     * 字节数据转字符串专用集合  
     */   
    private static final char[] HEX_CHAR= {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 
	 
    /** 
     * 加密算法RSA 
     */ 
    public static final String KEY_ALGORITHM = "RSA"; 
     
    /** 
     * 签名算法 
     */ 
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; 
 
    /** 
     * 获取公钥的key 
     */ 
    private static final String PUBLIC_KEY = "RSAPublicKey"; 
     
    /** 
     * 获取私钥的key 
     */ 
    private static final String PRIVATE_KEY = "RSAPrivateKey"; 
     
    /** 
     * RSA加密明文大小 
     */ 
    private static final int MAX_ENCRYPT_BLOCK = 117; 
     
    /** 
     * RSA解密密文大小 
     */ 
    private static final int MAX_DECRYPT_BLOCK = 128; 
 
    /** 
     * <p> 
     * 生成密钥公钥和私 
     * </p> 
     *  
     * @return 
     * @throws Exception 
     */ 
    public static Map<String, Object> genKeyPair() throws Exception { 
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); 
        keyPairGen.initialize(1024); 
        KeyPair keyPair = keyPairGen.generateKeyPair(); 
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); 
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); 
        Map<String, Object> keyMap = new HashMap<String, Object>(2); 
        keyMap.put(PUBLIC_KEY, publicKey); 
        keyMap.put(PRIVATE_KEY, privateKey); 
        return keyMap; 
    } 
     
    /** 
     * <p> 
     * 用私钥对信息生成数字签名 
     * </p> 
     *  
     * @param data 已加密数�? 
     * @param privateKey 私钥(BASE64编码) 
     *  
     * @return 
     * @throws Exception 
     */ 
    public static String sign(byte[] data, String privateKey) throws Exception { 
        byte[] keyBytes = Base64Utils.decode(privateKey); 
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); 
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 
        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); 
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); 
        signature.initSign(privateK); 
        signature.update(data); 
        return Base64Utils.encode(signature.sign()); 
    } 
 
    /** 
     * <p> 
     * 校验数字签名 
     * </p> 
     *  
     * @param data 已加密数�? 
     * @param publicKey 公钥(BASE64编码) 
     * @param sign 数字签名 
     *  
     * @return 
     * @throws Exception 
     *  
     */ 
    public static boolean verify(byte[] data, String publicKey, String sign) 
            throws Exception { 
        byte[] keyBytes = Base64Utils.decode(publicKey); 
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); 
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 
        PublicKey publicK = keyFactory.generatePublic(keySpec); 
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); 
        signature.initVerify(publicK); 
        signature.update(data); 
        return signature.verify(Base64Utils.decode(sign)); 
    } 
 
    /** 
     * <P> 
     * 私钥解密 
     * </p> 
     *  
     * @param encryptedData 已加密数�? 
     * @param privateKey 私钥(BASE64编码) 
     * @return 
     * @throws Exception 
     */ 
    public static byte[] decryptByPrivateKey(String date) 
            throws Exception { 
    	byte[] encryptedData = Base64Utils.decode(date.replace(" ", "+")) ; 
        byte[] keyBytes = Base64Utils.decode(privateKey); 
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); 
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); 
//        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
        cipher.init(Cipher.DECRYPT_MODE, privateK); 
        int inputLen = encryptedData.length; 
        ByteArrayOutputStream out = new ByteArrayOutputStream(); 
        int offSet = 0; 
        byte[] cache; 
        int i = 0; 
        // 对数据分段解�? 
        while (inputLen - offSet > 0) { 
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) { 
                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); 
            } else { 
                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); 
            } 
            out.write(cache, 0, cache.length); 
            i++; 
            offSet = i * MAX_DECRYPT_BLOCK; 
        } 
        byte[] decryptedData = out.toByteArray(); 
        out.close(); 
        return decryptedData; 
    } 
 
    /** 
     * <p> 
     * 公钥解密 
     * </p> 
     *  
     * @param encryptedData 已加密数�? 
     * @param publicKey 公钥(BASE64编码) 
     * @return 
     * @throws Exception 
     */ 
    public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) 
            throws Exception { 
        byte[] keyBytes = Base64Utils.decode(publicKey); 
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); 
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 
        Key publicK = keyFactory.generatePublic(x509KeySpec); 
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 
        cipher.init(Cipher.DECRYPT_MODE, publicK); 
        int inputLen = encryptedData.length; 
        ByteArrayOutputStream out = new ByteArrayOutputStream(); 
        int offSet = 0; 
        byte[] cache; 
        int i = 0; 
        // 对数据分段解�? 
        while (inputLen - offSet > 0) { 
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) { 
                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); 
            } else { 
                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); 
            } 
            out.write(cache, 0, cache.length); 
            i++; 
            offSet = i * MAX_DECRYPT_BLOCK; 
        } 
        byte[] decryptedData = out.toByteArray(); 
        out.close(); 
        return decryptedData; 
    } 
 
    /**  
     * 字节数据转十六进制字符串  
     * @param data 输入数据  
     * @return 十六进制内容  
     */   
    public static String byteArrayToString(byte[] data){   
        StringBuilder stringBuilder= new StringBuilder();   
        for (int i=0; i<data.length; i++){   
            //取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右�?  
            stringBuilder.append(HEX_CHAR[(data[i] & 0xf0)>>> 4]);   
            //取出字节的低四位 作为索引得到相应的十六进制标识符   
            stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);   
          /*  if (i<data.length-1){   
                stringBuilder.append(' ');   
            }  */ 
        }   
        return stringBuilder.toString();   
    } 
    /** 
     * <p> 
     * 公钥加密 
     * </p> 
     *  
     * @param data 源数�? 
     * @param publicKey 公钥(BASE64编码) 
     * @return 
     * @throws Exception 
     */ 
    public static String encryptByPublicKey(byte[] data) 
            throws Exception { 
        byte[] keyBytes = Base64Utils.decode(publicKey); 
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); 
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 
        Key publicK = keyFactory.generatePublic(x509KeySpec); 
        // 对数据加�? 
//        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
        cipher.init(Cipher.ENCRYPT_MODE, publicK); 
        int inputLen = data.length; 
        ByteArrayOutputStream out = new ByteArrayOutputStream(); 
        int offSet = 0; 
        byte[] cache; 
        int i = 0; 
        // 对数据分段加�? 
        while (inputLen - offSet > 0) { 
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { 
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); 
            } else { 
                cache = cipher.doFinal(data, offSet, inputLen - offSet); 
            } 
            out.write(cache, 0, cache.length); 
            i++; 
            offSet = i * MAX_ENCRYPT_BLOCK; 
        } 
        byte[] encryptedData = out.toByteArray(); 
        out.close(); 
//        return encryptedData; 
        return Base64Utils.encode(encryptedData); 
    } 
 
    /** 
     * <p> 
     * 私钥加密 
     * </p> 
     *  
     * @param data 源数�? 
     * @param privateKey 私钥(BASE64编码) 
     * @return 
     * @throws Exception 
     */ 
    public static byte[] encryptByPrivateKey(byte[] data, String privateKey) 
            throws Exception { 
        byte[] keyBytes = Base64Utils.decode(privateKey); 
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); 
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); 
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 
        cipher.init(Cipher.ENCRYPT_MODE, privateK); 
        int inputLen = data.length; 
        ByteArrayOutputStream out = new ByteArrayOutputStream(); 
        int offSet = 0; 
        byte[] cache; 
        int i = 0; 
        // 对数据分段加�? 
        while (inputLen - offSet > 0) { 
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { 
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); 
            } else { 
                cache = cipher.doFinal(data, offSet, inputLen - offSet); 
            } 
            out.write(cache, 0, cache.length); 
            i++; 
            offSet = i * MAX_ENCRYPT_BLOCK; 
        } 
        byte[] encryptedData = out.toByteArray(); 
        out.close(); 
        return encryptedData; 
    } 
 
    /** 
     * <p> 
     * 获取私钥 
     * </p> 
     *  
     * @param keyMap 密钥�? 
     * @return 
     * @throws Exception 
     */ 
    public static String getPrivateKey(Map<String, Object> keyMap) 
            throws Exception { 
        Key key = (Key) keyMap.get(PRIVATE_KEY); 
        return Base64Utils.encode(key.getEncoded()); 
    } 
 
    /** 
     * <p> 
     * 获取公钥 
     * </p> 
     *  
     * @param keyMap 密钥�? 
     * @return 
     * @throws Exception 
     */ 
    public static String getPublicKey(Map<String, Object> keyMap) 
            throws Exception { 
        Key key = (Key) keyMap.get(PUBLIC_KEY); 
        return Base64Utils.encode(key.getEncoded()); 
    } 
    /** 
	 * function:将json格式的字符串转化成键值对&形式,并且按ACSII码从小到大排�? 
	 * */ 
	public static String formatSignMsg(Map<String, String> paraMap,boolean urlencode,boolean keyLowerCase) { 
//		System.out.println("1.\n"+paraMap); 
		StringBuffer buff = new StringBuffer(); 
		List<Map.Entry<String, String>> keyList = new ArrayList<Map.Entry<String, String>>(paraMap.entrySet()); 
 
		Collections.sort(keyList,new Comparator<Map.Entry<String, String>>() { 
					@Override 
					public int compare(Map.Entry<String, String> src,Map.Entry<String, String> tar) { 
						return (src.getKey()).toString().compareTo(tar.getKey()); 
					} 
				}); 
 
		for (int i = 0; i < keyList.size(); i++) { 
			Map.Entry<String, String> item = keyList.get(i); 
			String key = item.getKey(); 
			String val = item.getValue(); 
			if (key!=null && !"".equals(key)) { 
				if (urlencode) { 
					try { 
						val = URLEncoder.encode(val, "UTF-8"); 
					} catch (UnsupportedEncodingException e) { 
						 
						e.printStackTrace(); 
						return null; 
					} 
 
				} 
				buff.append(keyLowerCase?key.toLowerCase():key); 
				buff.append(EQUAL_FLAG); 
				buff.append(val); 
				buff.append(APPEND_FLAG); 
 
			} 
		} 
 
		if (buff.length() > 0) { 
			System.out.println("2.\n"+buff.substring(0, buff.length() - 1)); 
			return buff.substring(0, buff.length() - 1); 
		}else return null; 
	} 
	public final static String Sha1(String s) { 
        char hexDigits[]={'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };        
        try { 
            byte[] btInput = s.getBytes("UTF-8"); 
            MessageDigest mdInst = MessageDigest.getInstance("sha-1"); 
            mdInst.update(btInput); 
            byte[] md = mdInst.digest(); 
            int j = md.length; 
            char str[] = new char[j * 2]; 
            int k = 0; 
            for (int i = 0; i < j; i++) { 
                byte byte0 = md[i]; 
                str[k++] = hexDigits[byte0 >>> 4 & 0xf]; 
                str[k++] = hexDigits[byte0 & 0xf]; 
            } 
//            System.out.println("aaa:\n"+new String(str)); 
            return new String(str); 
        } catch (Exception e) { 
            e.printStackTrace(); 
            return null; 
       } 
	} 
	/**  
     * 16进制的字符串表示转成字节数组  
     *  
     * @param hexString  
     *          16进制格式的字符串  
     * @return 转换后的字节数组  
     **/   
    public static byte[] hexStr2ByteArray(String hexString) {   
        if (hexString==null)   
            throw new IllegalArgumentException("this hexString must not be empty");   
       
        hexString = hexString.toLowerCase();   
        final byte[] byteArray = new byte[hexString.length() / 2];   
        int k = 0;   
        for (int i = 0; i < byteArray.length; i++) {   
			        	 //因为是16进制,最多只会占用4位,转换成字节需要两个16进制的字符,高位在先   
			            //将hex 转换成byte   "&" 操作为了防止负数的自动扩展   
			            // hex转换成byte 其实只占用了4位,然后把高位进行右移四位   
			            // 然后“|”操作  低四位 就能得到 两个 16进制数转换成一个byte.   
			            //    
            byte high = (byte) (Character.digit(hexString.charAt(k), 16) & 0xff);   
            byte low = (byte) (Character.digit(hexString.charAt(k + 1), 16) & 0xff);   
            byteArray[i] = (byte) (high << 4 | low);   
            k += 2;   
        }   
        return byteArray;   
    }   
}
发布评论

分享到:

IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

python3使用蓝本Blueprint详解
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。