6

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

 2 years ago
source link: https://laboo.top/2019/07/29/crypto/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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的加密代码不依赖其他包

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK