python3.X、nodejs、js、php、Android、AES通用加密解密方法
版权声明:
本文为博主原创文章,转载请声明原文链接...谢谢。o_0。
更新时间:
2019-09-04 11:56:09
温馨提示:
学无止境,技术类文章有它的时效性,请留意文章更新时间,如发现内容有误请留言指出,防止别人"踩坑",我会及时更新文章
aes加密方法在不同的语言中实现方式上填充方式是不同的,所以就导致啦使用中的一些麻烦,具体的原因请自行查找各种语言实现的时候用的是哪种填充方式就可以啦。
网上关于aes的加密文章已经很多啦但是很乱,每次到自己用的时候就像大海捞针一样!!!下面整理啦下个通用的实现方法,使用PKCS的方式来padding,因为NodeJS的库在auto_padding的状态下使用的也是PKCS,里面使用的加密key和偏移量统一都是用md5加密成32位key,然后再从key中截取一个16位的字符串做为依稀量使用的
php实现方法
class MyAES { static $key = ''; static $iv = ''; static function encryptToken($data, $skey) { MyAES::$key = md5($skey); MyAES::$iv = substr(MyAES::$key, 0, 16); $padding = 16 - (strlen($data) % 16); $data .= str_repeat(chr($padding), $padding); $data = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, MyAES::$key, $data, MCRYPT_MODE_CBC, MyAES::$iv); return base64_encode($data); } static function decryptToken($data, $skey) { MyAES::$key = md5($skey); MyAES::$iv = substr(MyAES::$key, 0, 16); $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, MyAES::$key, base64_decode($data), MCRYPT_MODE_CBC, MyAES::$iv); $padding = ord($data[strlen($data) - 1]); return substr($data, 0, -$padding); } } if (php_sapi_name() === 'cli') { $enstr = MyAES::encryptToken('www.zhaokeli.com111111', '735579768'); echo ('PHP encrypt: ' . $enstr . "\n"); echo ('PHP decrypt: ' . MyAES::decryptToken($enstr, '735579768')) . "\n"; }
js实现方法
下载 aes-encrypto.js文件
var text = 'www.zhaokeli.com1111111188888888'; var key = '735579768'; var enstr = AesEncrypt(text, key); console.log(enstr); console.log(AesDecrypt(enstr, key));
nodejs实现方法
var crypto = require('crypto'); function encrypt_token(data, skey) { var md5 = crypto.createHash("md5"); md5.update(skey); var key = md5.digest('hex'); var iv = key.substr(0, 16); console.log(key); console.log(iv); var cipher = crypto.createCipheriv('aes-256-cbc', key, iv); var restr = cipher.update(data, 'binary', 'base64'); restr += cipher.final('base64'); return restr; } function decrypt_token(data, skey) { var md5 = crypto.createHash("md5"); md5.update(skey); var key = md5.digest('hex'); var iv = key.substr(0, 16); var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv); var restr = decipher.update(data, 'base64', 'binary'); restr += decipher.final('binary'); return restr; } var enstr = encrypt_token('www.zhaokeli.com111111', '735579768'); console.log('NodeJS encrypt: ', enstr); console.log('NodeJS decrypt: ', decrypt_token(enstr, '735579768'));
python3.X实现方法
from Crypto.Cipher import AES import base64,hashlib class MyAES(object): def _cipher(self,skey): m=hashlib.md5() m.update(skey.encode()) key=m.hexdigest() iv=key[0:16] return AES.new(key=key, mode=AES.MODE_CBC, IV=iv) def _pad(self,s): return s + (AES.block_size - len(s) % AES.block_size) * chr(AES.block_size - len(s) % AES.block_size) def encrypt_token(self,data,skey): enda=self._cipher(skey).encrypt(self._pad(data)) return base64.b64encode(enda).decode() def decrypt_token(self,data,skey): data=base64.b64decode(data) deda=self._cipher(skey).decrypt(data).decode() padding = ord(deda[len(deda) - 1]); return deda[0:-padding] if __name__ == '__main__': aes=MyAES() enstr=aes.encrypt_token('www.zhaokeli.com111111','735579768') destr=aes.decrypt_token(enstr,'735579768') print('Python encrypt: '+enstr) print('Python decrypt: '+destr)
执行结果
Android平台实现,
因为android jdk中是不包含 sun.misc.base64decoder的所以要添加这个类的支持,下面下面 BASE64.jar 添加项目中就可以
package com.androidnodesocket; import java.security.MessageDigest; import java.util.Arrays; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import sun.misc.BASE64Decoder; class MyAES { public static String encrypt(String str,String skey){ try { String data = str; String key = md5(skey); String iv = key.substring(0,16); Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); int blockSize = cipher.getBlockSize(); byte[] dataBytes = data.getBytes(); int plaintextLength = dataBytes.length; int padding=blockSize - (plaintextLength % blockSize); plaintextLength = plaintextLength + padding; byte[] plaintext = new byte[plaintextLength]; Arrays.fill(plaintext,(byte)padding); System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length); SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); byte[] encrypted = cipher.doFinal(plaintext); return new sun.misc.BASE64Encoder().encode(encrypted); } catch (Exception e) { e.printStackTrace(); return null; } } public static String desEncrypt(String str,String skey) { try { String data = str; String key = md5(skey); String iv = key.substring(0,16); byte[] encrypted1 = new BASE64Decoder().decodeBuffer(data); Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); byte[] original = cipher.doFinal(encrypted1); int le=original[original.length-1]; byte[] restr=new byte[original.length-le]; System.arraycopy(original,0,restr,0,original.length-le); String originalString = new String(restr); return originalString; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 加密 * @param plaintext 明文 * @return ciphertext 密文 */ public final static String md5(String plaintext) { char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; try { byte[] btInput = plaintext.getBytes(); // 获得MD5摘要算法的 MessageDigest 对象 MessageDigest mdInst = MessageDigest.getInstance("MD5"); // 使用指定的字节更新摘要 mdInst.update(btInput); // 获得密文 byte[] md = mdInst.digest(); // 把密文转换成十六进制的字符串形式 int j = md.length; char str[] = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; str[k++] = hexDigits[byte0 >>> 4 & 0xf]; str[k++] = hexDigits[byte0 & 0xf]; } return new String(str); } catch (Exception e) { return null; } } }
用法
String enstr,destr; enstr=MyAES.encrypt("www.zhaokeli.com111111","735579768"); destr=MyAES.desEncrypt(enstr,"735579768"); showMsg(enstr); showMsg(destr);
效果