Java AES/ECB/PKCS5padding Encryption conversion Python
Note: Encryption mode 128-bit AES encryption mode is USED for ECB encryption, and Base64 transcoding is used after encryption.
Recently, I encountered AES encryption algorithm when docking with Java project. The Java code has securerandom.getInstance (“SHA1PRNG”). Converted to a Python
AES encryption
Advanced Encryption Standard (AES) is a specification established by the National Institute of Standards and Technology (NIST) in 2001 to encrypt electronic data. It is one of the most classical symmetric encryption and decryption algorithms. It is a grouping encryption standard. Each encryption block size is 128 bits, and the key length allowed is 128, 192 and 256 bits. This section describes only the ECB encryption mode. AES encryption mode: the ECB/CBC/CTR/OFB/CFB filling: pkcs5padding pkcs7padding/zeropadding/iso10126 / ansix923 data blocks: 128 a / 192 a / 256 aCopy the code
The ECB mode
The ECB mode, as the simplest working mode, directly groups the plaintext. Each group is encrypted separately, and each group is independent and has no context
Java encrypts Demo by default
Java’s default AES encryption mode is “AES/ECB/PKCS5Padding”.
Java Code Presentation
package com.qzd.hit.util;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class Demo {
/*** main
* @author qizai
* data: params
* encStr: Here, the length of the key must be a multiple of 16
*/
public static void main(String[] args) throws Exception {
// Encrypt Data
String key = "ROcb6JybnKILLOlO"; // Secret Key length must be (16 24 32)
String data = "[\" 123456789 \ "]"; // Content to be encrypted
String encStr = encrypt(data, key); // Content to be decrypted
System.out.println(encStr); //Encrypted data: w6oijM0xddQrItnH3UybLQ==
// Decrypt Data
String decStr = decrypt(encStr, key);
System.out.println(decStr); //Decrypted data: ["123456789"]
}
public static String encrypt(String content, String password) {
if (StringUtils.isEmpty(content) || StringUtils.isEmpty(password)) {
System.out.println("AES encryption params is null");
return null;
}
try {
// Create cipher
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
byte[] byteContent = content.getBytes("UTF-8");
// Initialize as cryptographic cipher
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));
byte[] encryptByte = cipher.doFinal(byteContent);
return org.apache.commons.codec.binary.Base64.encodeBase64String(encryptByte);
} catch (Exception e) {
System.out.println("AES encryption operation has exception,content:{},password:{}", content, password, e);
}
return null;
}
public static String decrypt(String encryptContent, String password) throws Exception {
if (StringUtils.isEmpty(encryptContent) || StringUtils.isEmpty(password)) {
System.out.println("AES The request parameter is null");
return null;
}
Cipher cipher = null;
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
// Set to decryption mode
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password));
// Perform decryption operation
byte[] result = cipher.doFinal(org.apache.commons.codec.binary.Base64.decodeBase64(encryptContent));
return new String(result, "UTF-8");
}
private static SecretKeySpec getSecretKey(final String password) throws NoSuchAlgorithmException {
// Generates the generator for the specified algorithm key
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(password.getBytes());
keyGenerator.init(128, random);
// Grnerate Key
SecretKey secretKey = keyGenerator.generateKey();
// Key converted to AES
return new SecretKeySpec(secretKey.getEncoded(), "AES"); }}Copy the code
Encryption notes:
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); // Generates the generator for the specified algorithm key
SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); // SHA1PRNG Random number algorithm
random.setSeed(password.getBytes());
keyGenerator.init(128, random);
SecretKey secretKey = keyGenerator.generateKey();
Copy the code
Python implementation AES/ECB/PKCS5padding
Install AES libraries (Windows)
pip install pycryptodome
Copy the code
Under Linux installation
pip install pycrypto
Copy the code
Related code implementation steps
import base64
import hashlib
import requests
from Crypto.Cipher import AES as _AES
class AES:
def __init__(self, key: str) :
"""Init aes object used by encrypt or decrypt. AES/ECB/PKCS5Padding same as aes in java default. """
self.aes = _AES.new(self.get_sha1prng_key(key), _AES.MODE_ECB)
@staticmethod
def get_sha1prng_key(key: str) - >bytes:
"""encrypt key with SHA1PRNG. same as java AES crypto key generator SHA1PRNG. SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" ); secureRandom.setSeed(decryptKey.getBytes()); keygen.init(128, secureRandom); :param string key: original key. :return bytes: encrypt key with SHA1PRNG, 128 bits or 16 long bytes. """
signature: bytes = hashlib.sha1(key.encode()).digest()
signature: bytes = hashlib.sha1(signature).digest()
return signature[:16]
@staticmethod
def padding(s: str) - >str:
"""Padding PKCS5"""
pad_num: int = 16 - len(s) % 16
return s + pad_num * chr(pad_num)
@staticmethod
def unpadding(s) :
"""Unpadding PKCS5"""
padding_num: int = ord(s[-1])
return s[: -padding_num]
def encrypt_to_bytes(self, content_str) :
"""From string encrypt to bytes ciphertext. """
content_bytes = self.padding(content_str).encode()
ciphertext_bytes = self.aes.encrypt(content_bytes)
return ciphertext_bytes
def encrypt_to_base64(self, content_str) :
"""From string encrypt to base64 ciphertext. """
ciphertext_bytes = self.encrypt_to_bytes(content_str)
ciphertext_bs64 = base64.b64encode(ciphertext_bytes).decode()
return ciphertext_bs64
def decrypt_from_bytes(self, ciphertext_bytes) :
"""From bytes ciphertext decrypt to string. """
content_bytes = self.aes.decrypt(ciphertext_bytes)
content_str = self.unpadding(content_bytes.decode())
return content_str
def decrypt_from_base64(self, ciphertext_bs64) :
"""From base64 ciphertext decrypt to string. """
ciphertext_bytes = base64.b64decode(ciphertext_bs64)
content_str = self.decrypt_from_bytes(ciphertext_bytes)
return content_str
def encrypt_to_bytes(content_str, encrypt_key: str) :
"""From string encrypt to bytes ciphertext. """
aes: AES = AES(encrypt_key)
ciphertext_bytes = aes.encrypt_to_bytes(content_str)
return ciphertext_bytes
def encrypt_to_base64(content_str, encrypt_key: str) - >str:
"""From string encrypt to base64 ciphertext. """
aes: AES = AES(encrypt_key)
ciphertext_bs64 = aes.encrypt_to_base64(content_str)
return ciphertext_bs64
def decrypt_from_bytes(ciphertext_bytes, decrypt_key: str) - >str:
"""From bytes ciphertext decrypt to string. """
aes: AES = AES(decrypt_key)
content_str = aes.decrypt_from_bytes(ciphertext_bytes)
return content_str
def decrypt_from_base64(ciphertext_bs64, decrypt_key: str) - >str:
"""From base64 ciphertext decrypt to string. """
aes: AES = AES(decrypt_key)
content_str = aes.decrypt_from_base64(ciphertext_bs64)
return content_str
if __name__ == "__main__":
key = "iC6qfFyiza8aq"
encrypt_str_data = "[\" 13811111111 \ "]"
et = encrypt_to_base64(encrypt_str_data, key)
print("Encrypted data:", et)
ret = decrypt_from_base64(et, key)
print("Decrypted data:", ret)
Copy the code
The key code
This method implements the conversion of key, the contents of the key encryption code in Java, which is returned as a hexadecimal string.
@staticmethod
def get_sha1prng_key(key: str) - >bytes:
"""encrypt key with SHA1PRNG. same as java AES crypto key generator SHA1PRNG. SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" ); secureRandom.setSeed(decryptKey.getBytes()); keygen.init(128, secureRandom); :param string key: original key. :return bytes: encrypt key with SHA1PRNG, 128 bits or 16 long bytes. """
signature: bytes = hashlib.sha1(key.encode()).digest()
signature: bytes = hashlib.sha1(signature).digest()
return signature[:16]
Copy the code
Simple version of
import base64
import hashlib
from Crypto.Cipher import AES
SECRET_KEY = 'iC6qfFyiza8aq' # key
class AesEncrypt(object) :
def __init__(self) :
self.key = self.getKey(SECRET_KEY)
self.mode = AES.MODE_ECB
def pading(self, text) :
"" processing of encrypted characters ""
return text + (len(self.key) - len(text) % len(self.key)) * chr(len(self.key) - len(text) % len(self.key))
def unpading(self, text) :
"" processing of decrypted characters ""
return text[0: -ord(text[-1:]]def getKey(self, key) :
""" processing of key,key length 16,24,32 ""
signature: bytes = hashlib.sha1(key.encode()).digest()
signature: bytes = hashlib.sha1(signature).digest()
return signature[:16]
def encrypt(self, text) :
""" Encryption function """
ecb_encrypt = AES.new(self.key, self.mode) # the ECB mode
ecb_text = ecb_encrypt.encrypt(bytes(self.pading(text), encoding="utf8"))
encrypt_string = base64.b64encode(ecb_text).decode()
return encrypt_string
def decrypt(self, text) :
""" Decryption function ""
decode = base64.b64decode(text)
ecb_decrypt = AES.new(self.key, self.mode) # the ECB mode
plain_text = ecb_decrypt.decrypt(decode)
decrypt_string = self.unpading(plain_text).decode()
return decrypt_string
if __name__ == '__main__':
aes_encrypt = AesEncrypt()
data = "[\" 13811111111 \ "]"
en = aes_encrypt.encrypt(data)
print("Encrypt data:", en)
dr = aes_encrypt.decrypt(en)
print("Decrypt data:", dr)
Copy the code
1. Perform sha1PRng encryption on the key, which is the get_sha1PRNG_key method in this article. Use the encrypted ciphertext as the AES key
Determine the AES encryption mode, such as ECB and CBC. The AES encryption mode is ECB/CBC/CTR/OFB/CFB
Padding, key and original text can be filled, NoPadding, NoPadding, 0 padding, and pkcs5padding.
4. Generally speaking, the incompatibility of encrypted content is basically caused by different key processing or incorrect filling.
[Refer to SHA1 algorithm]