python 3は、RSA鍵ペアを生成して復号化を実行する


詳細
暗号化は公開鍵を使用してデータを暗号化し、1024 bitのrsa公開鍵を使用する場合、一度に最大117 byteのデータしか暗号化できません.データ量がこの数を超えると、データをセグメント化する問題に関連する可能性があります.そして現在rsa 1024 bit長の鍵は安全ではないことが証明されており、できるだけ2048 bit長の鍵を使うべきである.2048 bit長の鍵は、245 byte長のデータを一度に暗号化することができる.この計算方法は2048 bit/8=256 byte−11 byte=245 byte長データである.鍵の長さから11 byteを差し引いた自分が最大1回でどれだけ暗号化できるかというデータです.それを超えるとエラーが発生するため、多くのプラットフォームがデータを公開鍵で暗号化することを要求しているため、セグメント化暗号化の問題に関連する可能性があります.また,復号時にはこの11 byteの減少は存在しないことに注意する.つまり、1024 bitの鍵は128 byteの長いデータを復号することができ、2048 bitの256 byteのデータを復号することができる.
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;

    /**
     * 

* *

* * @return * @throws Exception */ public static Map 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 keyMap = new HashMap(2); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** *

* *

* * @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()); } /** *

* *

* * @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)); } /** *

* *

* * @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; } /** *

* *

* * @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>> 4]); // stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]); /* if (i * * * * @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); } /** *

* *

* * @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; } /** *

* *

* * @param keyMap �? * @return * @throws Exception */ public static String getPrivateKey(Map keyMap) throws Exception { Key key = (Key) keyMap.get(PRIVATE_KEY); return Base64Utils.encode(key.getEncoded()); } /** *

* *

* * @param keyMap �? * @return * @throws Exception */ public static String getPublicKey(Map keyMap) throws Exception { Key key = (Key) keyMap.get(PUBLIC_KEY); return Base64Utils.encode(key.getEncoded()); } /** * function: json & , ACSII �? * */ public static String formatSignMsg(Map paraMap,boolean urlencode,boolean keyLowerCase) { // System.out.println("1.
"+paraMap); StringBuffer buff = new StringBuffer(); List> keyList = new ArrayList>(paraMap.entrySet()); Collections.sort(keyList,new Comparator>() { @Override public int compare(Map.Entry src,Map.Entry tar) { return (src.getKey()).toString().compareTo(tar.getKey()); } }); for (int i = 0; i < keyList.size(); i++) { Map.Entry 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.
"+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:
"+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; } }

117より長いセグメント暗号化
処理ロジックは、117の長さで分割し、分割が完了した後、byte配列に暗号化し、これらのbyte配列の長さは同じである.その後、これらの配列を前後に直列に接続し、base 64に変換して暗号化を完了する.
from pandas import json
import base64
import json
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.PublicKey import RSA
import requests
# app  ---    
# public_key ="dfafasddfasdfasdfasdfasdfasfasdf"
#      ---    
public_key = "dfadfasdfasdfaddds"
def get_encrypt_data(params):
    """    """
    params = json.dumps (params)
    params = params.encode ("utf-8")
    length = len (params)
    default_length = 117
    if length < default_length:
        return encrypt_data (params)
    offset = 0
    params_lst = []
    while length - offset > 0:
        if length - offset > default_length:
            params_lst.append (encrypt_data (params[offset:offset + default_length]))
        else:
            params_lst.append (encrypt_data (params[offset:length - offset]))
        offset += default_length

    n = len(params_lst)
    c = 1
    res = params_lst[0]
    while c < n:
        res = res+params_lst[c]
        c += 1
    return res

def encrypt_data(params):
    """         """
    key = public_key
    rsakey = RSA.importKey(base64.b64decode(key))
    cipher = Cipher_pkcs1_v1_5.new(rsakey)
    text = cipher.encrypt(params)
    return text

a="123134124151431234124121111111111111111123134123134124151431234124121111111111111111123134124151431234124121111111111111111123134124151431234124121111111111111111124151431234124121111111111111111123134124151431234124121111111111111111"

c = get_encrypt_data(a)
c2=base64.b64encode (c).decode('ascii')
print(c2)