密码学(一)——AES前端和后端的加解密以及对接

       最早系统学习密码学的知识是在软考过程中,当时也是半瓶子醋晃悠,我记得最近技术分享中也分享过一些相关的知识,可惜也没有细细分析,老大说要在数据在B/S传输过程中要加密,所以自己就先研究的AES前端和后端的加解密以及对接。这是两个过程:前端加密—传输到后台—后台解密、后台加密—传输—前台解密。

      AES的基本要求是,采用对称分组密码体制,密钥长度的最少支持为128、192、256,分组长度128位,算法应易于各种硬件和软件实现

加密模式

       AES分为几种模式,比如ECB,CBC,CFB等等,这些模式除了ECB由于没有使用IV而不太安全,其他模式差别并没有太明显,大部分的区别在IV和KEY来计算密文的方法略有区别。具体可参考WIKI的说明。另外,AES分为AES128,AES256等,表示期待秘钥的长度,比如AES256秘钥的长度应该是256/8的32字节,一些语言的库会进行自动截取,让人以为任何长度的秘钥都可以。而这其实是有区别的。

IV的作用

       IV称为初始向量,不同的IV加密后的字符串是不同的,加密和解密需要相同的IV,既然IV看起来和key一样,却还要多一个IV的目的,对于每个块来说,key是不变的,但是只有第一个块的IV是用户提供的,其他块IV都是自动生成。

IV的长度为16字节。超过或者不足,可能实现的库都会进行补齐或截断。但是由于块的长度是16字节,所以一般可以认为需要的IV是16字节。

PADDING

      AES块加密说过,PADDING是用来填充最后一块使得变成一整块,所以对于加密解密两端需要使用同一的PADDING模式,大部分PADDING模式为PKCS5, PKCS7, NOPADDING。

加密解密端

      对于加密端,应该包括:加密秘钥长度,秘钥,IV值,加密模式,PADDING方式。

      对于解密端,应该包括:解密秘钥长度,秘钥,IV值,解密模式,PADDING方式。

前端加解密:

<!DOCTYPEhtml>
<html>
<head>
    <title>aes demo</title>
    <meta charset="utf-8"/>
    <style>
        *{margin:0;padding:0}
        .demo-wrap{width: 400px;height:50px;margin: 50px auto auto auto}
    </style>
    <scriptsrc="./rollups/aes.js"></script>
<!--    <scriptsrc="./components/pad-zeropadding.js"></script>-->
</head>
<body>
<divclass="demo-wrap">
    <input type="text"id="data-ipt"/>
    <buttonοnclick="getAES();">AES加密</button>
    <buttonοnclick="getDAes();">AES解密</button>
    <br/>
    加密后的数据:
    <p id ="encrypted"></p>
    解密后的数据:
    <pid="decrypted"></p>
</div>
       <script>
        function getAesString(data,key,iv){//加密
                    
            var key  = CryptoJS.enc.Utf8.parse(key);
                     //alert(key);
            var iv   = CryptoJS.enc.Utf8.parse(iv);
            var encrypted =CryptoJS.AES.encrypt(data,key,
                    {
                        iv:iv,
                        mode:CryptoJS.mode.CBC,
                       padding:CryptoJS.pad.Pkcs7
                    });
            return encrypted.toString();    //返回的是base64格式的密文
        }
        function getDAesString(encrypted,key,iv){//解密
            var key  = CryptoJS.enc.Utf8.parse(key);
            var iv   = CryptoJS.enc.Utf8.parse(iv);
            var decrypted =CryptoJS.AES.decrypt(encrypted,key,
                    {
                        iv:iv,
                        mode:CryptoJS.mode.CBC,
                       padding:CryptoJS.pad.Pkcs7
                    });
            returndecrypted.toString(CryptoJS.enc.Utf8);      //
        }
        function getAES(){ //加密
            var data =document.getElementById("data-ipt").value;//明文
            var key  = 'abcdefgabcdefg12';  //密钥
            var iv   = 'abcdefgabcdefg12';
            var encrypted =getAesString(data,key,iv); //密文
                     var encrypted1 =CryptoJS.enc.Utf8.parse(encrypted);
           document.getElementById("encrypted").innerHTML = encrypted;
        }
 
        function getDAes(){//解密
            var encrypted =document.getElementById("encrypted").innerHTML; //密文
            var key  = 'abcdefgabcdefg12';
            var iv   = 'abcdefgabcdefg12';
            var decryptedStr =getDAesString(encrypted,key,iv);
                     alert(decryptedStr);
           document.getElementById("decrypted").innerHTML = decryptedStr;
        }
         </script>
</body>
</html>

      吃亏的地方在编码格式的问题上,用 crypto.js加密后的密文是base64格式的,而且解密的数据也必须是base64格式的, 这样才能和后台做对接。

现在来看后台代码:

packagecom.test.aes;
 
importjava.io.UnsupportedEncodingException;
 
importjavax.crypto.Cipher;
importjavax.crypto.spec.IvParameterSpec;
importjavax.crypto.spec.SecretKeySpec;
 
importorg.apache.commons.codec.binary.Base64;
 
public classAesCBC {
       public static void main(String[] args)throws UnsupportedEncodingException { 
        Stringcontent="12345678"; 
        Stringkey="abcdefgabcdefg12"; 
        Stringiv="abcdefgabcdefg12"; 
        //加密
        byte[ ]encrypted=AES_CBC_Encrypt(content.getBytes(), key.getBytes(), iv.getBytes());
        //解密
        byte[ ]decrypted=AES_CBC_Decrypt(encrypted, key.getBytes(), iv.getBytes()); 
       
        System.out.println("解密后:"+byteToHexString(decrypted));
       System.out.println(byteToString(decrypted));
    } 
    public static String byteToString(byte[ ]byte1){
         returnnew String(byte1);
    }
    public static byte[] AES_CBC_Encrypt(byte[]content, byte[] keyBytes, byte[] iv){ 
         
        try{ 
            SecretKeySpec key = newSecretKeySpec(keyBytes, "AES");
            Ciphercipher=Cipher.getInstance("AES/CBC/PKCS5Padding"); 
            cipher.init(Cipher.ENCRYPT_MODE,key, new IvParameterSpec(iv)); 
            byte[]result=cipher.doFinal(content);
            return result;
        }catch (Exception e) { 
           System.out.println("exception:"+e.toString()); 
        }  
        return null; 
    } 
     
    public static byte[] AES_CBC_Decrypt(byte[]content, byte[] keyBytes, byte[] iv){ 
         
        try{      
            SecretKeySpec key = newSecretKeySpec(keyBytes, "AES");
            Ciphercipher=Cipher.getInstance("AES/CBC/PKCS5Padding"); 
            cipher.init(Cipher.DECRYPT_MODE,key, new IvParameterSpec(iv)); 
            byte[]result=cipher.doFinal(content); 
            return result; 
        }catch (Exception e) { 
            // TODO Auto-generated catchblock 
            System.out.println("exception:"+e.toString()); 
        }  
        return null; 
    } 
/**
     * 字符串装换成base64
     * 
     * @param key
     * @return
     * @throws Exception
     */ 
    public static byte[] decryptBASE64(Stringkey) throws Exception { 
         returnBase64.decodeBase64(key.getBytes());
    } 
     
    /**
     *二进制装换成base64
     * 
     * @param key
     * @return
     * @throws Exception
     */ 
    public static String encryptBASE64(byte[]key) throws Exception { 
         returnnew String(Base64.encodeBase64(key));
    }
}
 

      前端和后端是分开来做的但是都在AES在线生成器中加密过,得到的都是相同的密文。

      AES收获很多,这里可能有很多坑,大家踩一踩,然后交流交流。做到最后老大说用RSA算法,今天研究的是RSA也算有进度,等待分享。

 

附录

http://www.cnblogs.com/vmax-tam/p/4624032.html

http://blog.csdn.net/chence19871/article/details/27653805

http://blog.csdn.net/vieri_32/article/details/48345023

http://blog.csdn.net/defonds/article/details/42775183

http://blog.csdn.net/cfl20121314/article/details/49749275

http://www.cjjjs.com/paper/xmkf/2016629102258195.aspx

http://www.cjjjs.com/paper/xmkf/201663012403485.aspx

http://www.cnblogs.com/shoneworn/p/5071305.html

 以上源码下载

评论 46
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值