python3.X、nodejs、php、Android、AES通用加密解密方法

来源:赵克立 分类: 网络安全 标签:加密解密发布时间:2017-12-30 15:28:17浏览:246
版权声明:
本文为博主原创文章,转载请声明原文链接...谢谢。o_0。
温馨提示:
技术类文章有它的时效性,请留意文章更新时间以及软件的版本
更新时间:
2018-01-15 10:43:55

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";
}

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)

执行结果

image.png

Android平台实现,

因为android jdk中是不包含 sun.misc.base64decoder的所以要添加这个类的支持,下面下面 BASE64.jar   添加项目中就可以

BASE64.zip

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

效果

GIF.gif


微信号:mokuyu QQ群:215861553 紧急求助须知
留下一点心意, :)
点击更换验证码
留言