转载

Python与Java程序RSA,AES加密相互通信

python 版本 3.6 , 在windows以及linux上都进行过测试

由于 pythonrsa 加密存在长度限制, 虽然可以通过分片加密来解决,

但是更好的做法是通过 rsa 加密传输 aes密钥 给服务器, 携带的信息通过该密钥进行 aes 加密,

服务器通过 rsa私钥 得到 aes密钥 后解析信息, 并继续使用密钥进行双向通信

python中加密使用 pycryptodome 模块

pip install pycryptodome

Python

其中接受的参数text,key均为字符串

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from Crypto.Cipher import AES
from base64 import b64decode
from base64 import b64encode
import re


def rsa_encode(text, public_key):
    key = RSA.importKey(b64decode(public_key))
    cipher = PKCS1_v1_5.new(key)
    return b64encode(cipher.encrypt(text.encode(encoding='utf-8'))).decode('utf-8')


def aes_encode(text, key):
    key = key.encode('utf-8')
    cipher = AES.new(key, AES.MODE_CBC, key)
    text = text + (16 - len(text) % 16) * chr(16 - len(text) % 16)
    return b64encode(cipher.encrypt(text.encode(encoding='utf-8'))).decode('utf-8')


def aes_decode(cipher_text, key):
    key = key.encode('utf-8')
    cipher = AES.new(key, AES.MODE_CBC, key)
    text = cipher.decrypt(b64decode(cipher_text)).decode('utf-8')
    return re.compile('[//x00-//x08//x0b-//x0c//x0e-//x1f/n/r/t]').sub('', text)

Java

java的加密代码不依赖其他包

AesUtils

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.UUID;

public class AesUtils {

    private static final String TYPE = "AES";
    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
    private static final String CHARSET = "UTF-8";

    public static String createKey(){
        return UUID.randomUUID().toString().replace("-","").substring(16);
    }

    public static String encrypt(String data, String key) throws Exception {
        IvParameterSpec ivParameterSpec = new IvParameterSpec(key.getBytes());
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), TYPE);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParameterSpec);
        return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes(CHARSET)));
    }

    public static String decrypt(String data, String key) throws Exception {
        IvParameterSpec ivParameterSpec = new IvParameterSpec(key.getBytes());
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), TYPE);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
        return new String(cipher.doFinal(Base64.getDecoder().decode(data.getBytes())), CHARSET);
    }
}

RsaUtils

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RsaUtils {

    private static final String TYPE = "RSA";
    private static final String ALGORITHM = "RSA/ECB/PKCS1PADDING";
    private static final String CHARSET = "UTF-8";
    private static final int KEY_SIZE = 1024;

    public static KeyPair createKeyPair() {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(TYPE);
            keyPairGenerator.initialize(KEY_SIZE);
            return keyPairGenerator.generateKeyPair();
        } catch (Exception e) {
            return null;
        }
    }

    public static String getPublicKey(KeyPair keyPair) {
        return Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
    }

    public static String getPrivateKey(KeyPair keyPair) {
        return Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
    }

    public static String encrypt(String data, String publicKeyString) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        KeyFactory keyFactory = KeyFactory.getInstance(TYPE);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyString));
        RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return Base64.getEncoder().encodeToString(splitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET)));
    }

    public static String decrypt(String data, String privateKeyString) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        KeyFactory keyFactory = KeyFactory.getInstance(TYPE);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyString));
        RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return new String(splitCodec(cipher, Cipher.DECRYPT_MODE, Base64.getDecoder().decode(data)), CHARSET);
    }

    private static byte[] splitCodec(Cipher cipher, int mode, byte[] data) throws Exception {
        int maxBlock = KEY_SIZE / 8 - (mode == Cipher.DECRYPT_MODE ? 0 : 11);
        try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            byte[] buffer;
            for (int offset = 0; offset < data.length; offset += maxBlock) {
                buffer = cipher.doFinal(data, offset, Math.min(maxBlock, data.length - offset));
                out.write(buffer, 0, buffer.length);
            }
            return out.toByteArray();
        }
    }
}
原文  https://laboo.top/2019/07/29/crypto/
正文到此结束
Loading...