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

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

由于pythonrsa加密存在长度限制, 虽然可以通过分片加密来解决,
但是更好的做法是通过rsa加密传输aes密钥给服务器, 携带的信息通过该密钥进行aes加密,
服务器通过rsa私钥得到aes密钥后解析信息, 并继续使用密钥进行双向通信

python中加密使用pycryptodome模块

1
pip install pycryptodome

Python

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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();
}
}
}