AES加密

AES是一个对称密码,旨在取代DES成为广泛使用的标准。

一、AES的加密过程

 

二、AES的数据结构

加密解密算法的输入是一个128位分组。这些分组被描述成4×4的字节方阵,这个分组被复制到state数组中,并在加密和解密的每一阶段都被修改。在字节方阵中,每一格都是一个字,包含了4字节。在矩阵中字是按列排序的。

 

 加密由N轮构成,轮数依赖于密钥长度:16字节密钥对应10轮,24字节密钥对应12轮,32字节对应14轮。

 

三、加密解密的详细结构

AES未使用Feistel结构。其前N-1轮由4个不同的变换组成:字节代替、行移位、列混淆和轮密钥加。最后一轮仅包含三个变换。而在第一轮前面有一个起始的单变换(轮密钥加),可以视为0轮。

  字节代替SubBytes):用一个S盒完成分组的字节到字节的代替。

  行移位ShiftRows):一个简单的置换。

  列混淆MixColumns):利用域GF(28)上的算术特性的一个代替。

  轮密钥加AddRoundKey):当前分组和扩展密钥的一部分进行按位异或XOR

 

首尾使用轮密钥加的理由:若将其他不需要密钥的阶段放在首尾,在不知道密钥的情况下就能计算其逆,这就不能增加算法的安全性。

加密原理:轮密钥加实际是一种Vernam密码形式,其本身不难被破解。另外三个阶段一起提供了混淆、扩散和非线性功能。这三个阶段没有涉及密钥,就它们自身而言,并未提供算法的安全性。然而,该算法经历一个分组的XOR加密(轮密钥加),再对该分组混淆扩散(其他三个阶段),再接着又是XOR加密,如此交替进行,这种方式非常有效非常安全。

可逆原理:每个阶段均可逆。对字节代替、行移位和列混淆,在解密算法中用它们相对应的逆函数。轮密钥加的逆就是用同样的轮密钥和分组相异或,其原理就是ABB = A。和大多数分组密码一样,AES解密算法按逆序利用扩展密钥,然而其解密算法和加密算法并不一样,这是由AES的特定结构决定的。图5.3中加密和解密流程在纵向上是相反的,在每个水平点上,state数组在加密和解密函数中都是一样的。

 


常用语言的AES加密

PHP 7.1以下版本:

/**
  * HMAC-SHA256加密算法生成签名
  * @param $secret_key                   //生成签名的秘钥
  * @param  $base_str                    //生成签名的基本字符串(签名信息)
  * @return string
  */
function  get_signature_hmac_sha256( $secret_key , $base_str )
{
     $signature_info  base64_encode (hash_hmac( 'sha256' $base_str $secret_key , true));
     return  $signature_info ;
}
 
/**
  * AES128加密算法生成签名
  * @param $secret_key                   //生成签名的秘钥
  * @param  $base_str                    //生成签名的基本字符串(签名信息)
  * @return string
  */
function  get_signature_aes128( $secret_key , $base_str )
{
     $size  = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
     $input  = pkcs5_pad( $base_str $size );
     $td  = mcrypt_module_open(MCRYPT_RIJNDAEL_128,  '' , MCRYPT_MODE_ECB,  '' );
     $iv  = mcrypt_create_iv (mcrypt_enc_get_iv_size( $td ), MCRYPT_RAND);
     mcrypt_generic_init( $td $secret_key $iv );
     $data  = mcrypt_generic( $td $input );
     mcrypt_generic_deinit( $td );
     mcrypt_module_close( $td );
     $signature_info  base64_encode ( $data );
 
     return  $signature_info ;
}
 
//AES 相关函数
function  pkcs5_pad ( $text $blocksize )
{
     $pad  $blocksize  - ( strlen ( $text ) %  $blocksize );
     return  $text  str_repeat ( chr ( $pad ),  $pad );
}
PHP 7.1以上版本:
/***
 * AES128加密算法加密明文
 * @author haolin.jiang<haolin.jiang@starcor.cn>
 * @param $base_str //待加密字符串
 * @param $key //秘钥
 * @return string //生成的签名
 */
    static public function encrypt_aes128($base_str, $key)
    {
       $encrypt_str = openssl_encrypt($base_str,'AES-128-ECB',$key,OPENSSL_RAW_DATA);
        return base64_encode($encrypt_str);
    }


    /**
     * AES128解密算法解密密文
    * @author haolin.jiang<haolin.jiang@starcor.cn>
     * @param $encrypt_str
     * @param $encrypt_key
     * @return string
     */
   static public function decrypt_aes128($encrypt_str, $encrypt_key)
    {
       $decrypt_str = openssl_decrypt(base64_decode($encrypt_str),'AES-128-ECB',$encrypt_key,OPENSSL_RAW_DATA);
        return $decrypt_str;
    }

JS(基于 CryptoJS

<script src="./CryptoJS v3.1.2/rollups/aes.js"></script> 
<script src="./CryptoJS v3.1.2/components/mode-ecb-min.js"></script>

<script type="text/javascript">
     //加密key
     var key = CryptoJS.enc.Utf8.parse('1111111111111111');//转为128 bit
     //待加密字符
     var str = CryptoJS.enc.Utf8.parse('12345');
     var result = CryptoJS.AES.encrypt(str,key,{
            mode:CryptoJS.mode.ECB,
            padding:CryptoJS.pad.Pkcs7
     });
    console.log(result.toString());

</script>


JAVA

import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;


class EncryptDemo {
    public static void main(String[] args) throws Exception
    {
        EncryptDemo demo = new EncryptDemo();
        String key = "1111111111111111";
        String input = "12345";
        String a = demo.enctypt(input,key);
        System.out.println(a);
        String b = demo.decrypt(a,key);
        System.out.println(b);
        //比较加密之前的串与解密出来的串是否一致
        if (input.equals(b))
        {
            System.out.println("相等");
        } else
        {
            System.out.println("不相等");
        }
    }

    /*
    * @name 加密
    * @param string input 待加密的字符
    * @param string key   加密key
    * @return string      加密后的字符
    * */
    public String enctypt(String input, String key) throws Exception
    {
        if (key == null)
        {
            System.out.print("加密key不能为空");
            return null;
        }
        System.out.println(key.length());
        if (key.length() != 16)
        {
            System.out.print("加密key长度必须为16");
            return null;
        }
        byte[] raw = key.getBytes("utf-8");//将字符串转化为字节数组
        SecretKeySpec keySpec = new SecretKeySpec(raw,"AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//算法/模式/填充
        cipher.init(cipher.ENCRYPT_MODE,keySpec);
        byte[] encrypted = cipher.doFinal(input.getBytes("utf-8"));
        return new BASE64Encoder().encode(encrypted);
    }

    /*
    * @name 解密
    * @param String input 加密后的串
    * @param String key   解密key
    * @return string
    * */
    public String decrypt(String input,String key) throws Exception
    {
        try {
            if (key == null)
            {
                System.out.print("解密key不能为空");
                return null;
            }
            if (key.length() != 16)
            {
                System.out.print("解密key的长度必须为16");
                return null;
            }
            byte[] raw = key.getBytes("utf-8");
            SecretKeySpec keySpec = new SecretKeySpec(raw,"AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(cipher.DECRYPT_MODE,keySpec);
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(input);//base64位解密
            try {
                byte[] encrypted = cipher.doFinal(encrypted1);
                String str = new String(encrypted,"utf-8");
                return str;
            } catch (Exception e)
            {
                e.getStackTrace();
            }
        } catch (Exception e)
        {
            e.getStackTrace();
        }
        return null;
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值