背景:
因項目需要,需要將一個python2編寫的aes加密方式改為java實現。
1.源python2實現
from Crypto.Cipher import AES from binascii import b2a_hex, a2b_hex import hashlib import urllib class aesCrypt(): def __init__(self, undealKey): key = turnMd5(undealKey) print undealKey dealKey = dealKeyAndIV(key.lower()) self.key = dealKey # self.iv = iv self.mode = AES.MODE_ECB self.BS = AES.block_size # 補位 self.pad = lambda s: s + (self.BS - len(s) % self.BS) * chr(self.BS - len(s) % self.BS) self.unpad = lambda s: s[0:-ord(s[-1])] def encrypt(self, text): text = self.pad(text) cryptor = AES.new(self.key, self.mode) # 目前AES-128 足夠目前使用 ciphertext = cryptor.encrypt(text) # 把加密后的字符串轉化為16進制字符串 return b2a_hex(ciphertext) # 解密后,去掉補足的空格用strip() 去掉 def decrypt(self, text): cryptor = AES.new(self.key, self.mode) plain_text = cryptor.decrypt(a2b_hex(text)) return self.unpad(plain_text.rstrip('\0')) def turnHex(character): <略> def debugPrint(str): print str def dealKeyAndIV(undealKey):
<略>
def turnMd5(str): <略>
2.經歷
1. 我只有python3的環境,因使用到
Crypto
這個package的很難安裝上去,經過多種嘗試,使用pycryptodome替代,故需要修改部分代碼
2. 改成python3的文件
from Crypto.Cipher import AES from binascii import b2a_hex, a2b_hex import hashlib import urllib class aesCrypt(): def __init__(self, undealKey): key = turnMd5(undealKey) print(undealKey) dealKey = dealKeyAndIV(key.lower()) self.key = dealKey # self.iv = iv self.mode = AES.MODE_ECB self.BS = AES.block_size # 補位 self.pad = lambda s: s + (self.BS - len(s) % self.BS) * chr(self.BS - len(s) % self.BS) self.unpad = lambda s: s[0:-ord(s[-1])] def encrypt(self, text): text = self.pad(text) #finalkey=bytes([239,159,125,206,247,119,225,116,254,91,100,130,255,144,207,70]) cryptor = AES.new(bytes(self.key), self.mode) # 目前AES-128 足夠目前使用 #ss=bytes([67, 122, 99, 115, 81, 111, 68, 112, 67, 47, 67, 75, 48, 108, 98, 90, 99, 68, 47, 115, 88, 87, 52, 65, 43, 105, 119, 83, 72, 122, 88, 109, 55, 110, 98, 54, 102, 85, 89, 84, 56, 89, 117, 120, 102, 79, 110, 78, 70, 69, 120, 104, 97, 48, 68, 115, 83, 112, 89, 85, 84, 57, 49, 98, 113, 66, 120, 77, 107, 108, 52, 74, 105, 99, 72, 56, 49, 112, 105, 71, 106, 116, 103, 77, 87, 69, 71, 57, 43, 52, 69, 120, 54, 86, 82, 56, 56, 51, 102, 88, 74, 52, 112, 86, 117, 110, 120, 68, 117, 68, 100, 56, 53, 100, 109, 109, 88, 82, 106, 110, 48, 118, 107, 99, 115, 105, 89, 102, 97, 51, 110, 122, 72, 85, 122, 54, 67, 107, 55, 74, 85, 109, 115, 49, 73, 79, 99, 78, 76, 86, 66, 53, 87, 110, 53, 110, 106, 68, 76, 83, 65, 70, 114, 84, 106, 71, 68, 87, 110, 73, 69, 61, 4, 4, 4, 4]) #ss=text.encode() #print(a2b_hex(ss)) #print(a2b_hex(ss)) ciphertext = cryptor.encrypt(text.encode("utf-8")) # 把加密后的字符串轉化為16進制字符串 return b2a_hex(ciphertext) # 解密后,去掉補足的空格用strip() 去掉 def decrypt(self, text): cryptor = AES.new(self.key, self.mode) plain_text = cryptor.decrypt(a2b_hex(text)) return self.unpad(plain_text.rstrip('\0')) def turnHex(character): value = ord(character) # print value temp = value - 48 if value - 48 > 9: if (value - 97 <= 5) & (value - 97 >= 0): temp = value - 87 return tempdef dealKeyAndIV(undealKey): flag = 0 result=[] # debugPrint 'len=',len(undealKey)/2 while flag < len(undealKey)/2: characterH = undealKey[flag*2] # debugPrint characterH highBit = turnHex(characterH) * 16 # debugPrint highBit characterL = undealKey[flag*2+1] # debugPrint characterL lowBit = turnHex(characterL) # debugPrint lowBit ascValue = highBit+lowBit # debugPrint ascValue result.append(ascValue) # debugPrint result flag += 1 # print '-------' return resultdef turnMd5(str): m2 = hashlib.md5() data = str.encode(encoding="utf-8") m2.update(data) return m2.hexdigest()
改寫java程序
private static byte[] pading(String str){ byte[] strBs=str.getBytes(); int n=strBs.length/16; byte[] pading=new byte[16*(n+1)]; System.arraycopy(strBs, 0, pading, 0, strBs.length); //不足16位的進行補足 int len=16 - str.length()%16; for(int i=strBs.length;i<pading.length;i++){ pading[i]=(byte)len; } return pading; } public static String bytesToHexString(byte[] src){ StringBuilder stringBuilder = new StringBuilder(""); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); } public static String MD5Encode(String source, String encoding, boolean uppercase) { String result = null; try { result = source; // 獲得MD5摘要對象 MessageDigest messageDigest = MessageDigest.getInstance("MD5"); // 使用指定的字節數組更新摘要信息 messageDigest.update(result.getBytes(encoding)); // messageDigest.digest()獲得16位長度 result = bytesToHexString(messageDigest.digest()); } catch (Exception e) { e.printStackTrace(); } return uppercase ? result.toUpperCase() : result; } public static Integer turnHex(char c){ int ret=0; switch(c){ case '0':return 0; case '1':return 1; case '2':return 2; case '3':return 3; case '4':return 4; case '5':return 5; case '6':return 6; case '7':return 7; case '8':return 8; case '9':return 9; case 'a':return 10; case 'b':return 11; case 'c':return 12; case 'd':return 13; case 'e':return 14; case 'f':return 15; } return ret; } private static byte[] dealKeyAndIV(String str){ byte[] keys=new byte[16]; int flag = 0; while(flag < str.length()/2){ char characterH =str.charAt(flag*2); int highBit = turnHex(characterH) * 16; char characterL = str.charAt(flag*2+1); int lowBit = turnHex(characterL); int ascValue = highBit+lowBit; keys[flag]=(byte) ascValue; //System.out.println(ascValue); flag += 1; } return keys; } public static String encrypt() throws Exception { try { String data = "CzcsQoDpC/CK0lbZcD/sXW4A+iwSHzXm7nb6fUYT8YuxfOnNFExha0DsSpYUT91bqBxMkl4JicH81piGjtgMWEG9+4Ex6VR883fXJ4pVunxDuDd85dmmXRjn0vkcsiYfa3nzHUz6Ck7JUms1IOcNLVB5Wn5njDLSAFrTjGDWnIE="; String key = "IMgzwYRjA3sZgiXl"; String md5key=MD5Encode(key,"utf-8",false); //'ef9f7dcef777e174fe5b6482ff90cf46' //String finalKey = dealKeyAndIV(md5key); //System.out.println(finalKey.length()); //System.out.println("c3afc29f7dc38ec3b777c3a174c3be5b64c282c3bfc290c38f46".length()); //String ss=bytesToHexString(finalKey.getBytes());//b'c3afc29f7dc38ec3b777c3a174c3be5b64c282c3bfc290c38f46' Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding"); int blockSize = cipher.getBlockSize(); byte[] plaintext=pading(data); /* byte[] dataBytes = data.getBytes(); int plaintextLength = dataBytes.length; if (plaintextLength % blockSize != 0) { plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize)); } byte[] plaintext = new byte[plaintextLength]; System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);*/ byte[] keys=dealKeyAndIV(md5key); // byte[] keys=new byte[]{(byte)239,(byte)159,125,(byte)206,(byte)247,119,(byte)225,116,(byte)254,91,100,(byte)130,(byte)255,(byte)144,(byte)207,70}; SecretKeySpec keyspec = new SecretKeySpec(keys, "AES"); cipher.init(Cipher.ENCRYPT_MODE, keyspec); //byte[] bb=new byte[]{67, 122, 99, 115, 81, 111, 68, 112, 67, 47, 67, 75, 48, 108, 98, 90, 99, 68, 47, 115, 88, 87, 52, 65, 43, 105, 119, 83, 72, 122, 88, 109, 55, 110, 98, 54, 102, 85, 89, 84, 56, 89, 117, 120, 102, 79, 110, 78, 70, 69, 120, 104, 97, 48, 68, 115, 83, 112, 89, 85, 84, 57, 49, 98, 113, 66, 120, 77, 107, 108, 52, 74, 105, 99, 72, 56, 49, 112, 105, 71, 106, 116, 103, 77, 87, 69, 71, 57, 43, 52, 69, 120, 54, 86, 82, 56, 56, 51, 102, 88, 74, 52, 112, 86, 117, 110, 120, 68, 117, 68, 100, 56, 53, 100, 109, 109, 88, 82, 106, 110, 48, 118, 107, 99, 115, 105, 89, 102, 97, 51, 110, 122, 72, 85, 122, 54, 67, 107, 55, 74, 85, 109, 115, 49, 73, 79, 99, 78, 76, 86, 66, 53, 87, 110, 53, 110, 106, 68, 76, 83, 65, 70, 114, 84, 106, 71, 68, 87, 110, 73, 69, 61, 4, 4, 4, 4}; byte[] encrypted = cipher.doFinal(plaintext); return bytesToHexString(encrypted); //return new sun.misc.BASE64Encoder().encode(encrypted); } catch (Exception e) { e.printStackTrace(); return null; } }
注意點
1. 是模式ECB,BCB等
2.填充方式
自定義填充