• 小谈加密算法


    1、为什么要用加密

    网站中有很多类似金钱、密码等重要业务数据,一旦被监听、拦截,可能会造成严重的损失。
    比如下图:

    我们可以很容易的看到某个请求的相关参数数据
    这里写图片描述

    2、应用场景

    加密算法有很多种应用场景,最常见的是用户登录、身份验证、验签等等。目的在于通过算法,将明文转换为密文。将明文转换为密文只是第一步,更深一步的做法是结合sessionId、随机数、token或者https等,最大限度的防止信息被盗取。

    3、类型

    加密算法通常分为对称性加密算法和非对称性加密算法。

    3.1 对称性加密

    只存在一把钥匙key,如果A想要与B通讯,那么A使用钥匙进行加密,B接收到密文的钥匙后,使用钥匙解密,获得明文信息。

    这里写图片描述

    优缺点
    效率高、使用维护简单,缺点就是密码一旦泄露,通讯信息就会暴露。

    常用加密算法:
    DES、三重DES、AES等,稍后会以AES为例,介绍具体用法。

    3.2 非对称加密

    非对称加密有两把钥匙:私钥和公钥。
    这里有几个原则和前提需要先说明:
    1)公钥和私钥是成对出现的。
    2)公开的是公钥,私钥只有自己知道。
    3)用公钥加密的信息,只能用对应的私钥进行解密。

    这里写图片描述

    A、B各有一对密钥,A的密钥包括:公钥01、私钥02,B的密钥包括:公钥03、私钥04。其中,A拥有B的公钥03,同样的,B也拥有A的公钥01。

    当A要与B通讯时,A使用B的公钥03加密,当B拿到密文后,拿自己的私钥04解密。

    优缺点:
    非对称加密的优缺点正好与对称加密相反,可参照上面。

    常用加密算法:
    RSA,DSA,ECC

    除了上面两种主要类型的加密算法,还有一大类是线性散列算法,也叫签名算法。常用算法有:MD5,SHA1,HMAC。这类算法可以生成一长串不可逆的密文,经常用在校验数据在传输过程中是否经过修改。

    4、实例

    场景:用户登录,使用res加密,前端js加密,后端解密。

    4.1 js文件

       //加密key
       var key =CryptoJS.enc.Utf8.parse("*******");  
       //pwd为加密信息 
       var srcs = CryptoJS.enc.Utf8.parse(pwd);  
       var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});

    4.2 后台解密

        /**
         * 密钥,要与加密时的密钥保持一致
         */
        private static final String KEY = "*******";
        /**
         * 算法
         */
        private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";
    
        /**
         * aes解密
         * 
         * @param encrypt
         *            内容
         * @return
         * @throws Exception
         */
        public static String aesDecrypt(String encrypt) throws Exception {
            return aesDecrypt(encrypt, KEY);
        }
    
        /**
         * aes加密
         * 
         * @param content
         * @return
         * @throws Exception
         */
        public static String aesEncrypt(String content) throws Exception {
            return aesEncrypt(content, KEY);
        }
    
        /**
         * 将byte[]转为各种进制的字符串
         * 
         * @param bytes
         *            byte[]
         * @param radix
         *            可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制
         * @return 转换后的字符串
         */
        public static String binary(byte[] bytes, int radix) {
            return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数
        }
    
        /**
         * base 64 encode
         * 
         * @param bytes
         *            待编码的byte[]
         * @return 编码后的base 64 code
         */
        public static String base64Encode(byte[] bytes) {
            return Base64.encodeBase64String(bytes);
        }
    
        /**
         * base 64 decode
         * 
         * @param base64Code
         *            待解码的base 64 code
         * @return 解码后的byte[]
         * @throws Exception
         */
    
         public static byte[] base64Decode(String base64Code) throws Exception{
             return StringUtil.isEmpty(base64Code) ? null : new  BASE64Decoder().decodeBuffer(base64Code); 
         }
    
    
        /**
         * AES加密
         * 
         * @param content
         *            待加密的内容
         * @param encryptKey
         *            加密密钥
         * @return 加密后的byte[]
         * @throws Exception
         */
        public static byte[] aesEncryptToBytes(String content, String encryptKey)
                throws Exception {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            kgen.init(128);
            Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
            cipher.init(Cipher.ENCRYPT_MODE,
                    new SecretKeySpec(encryptKey.getBytes(), "AES"));
    
            return cipher.doFinal(content.getBytes("utf-8"));
        }
    
        /**
         * AES加密为base 64 code
         * 
         * @param content
         *            待加密的内容
         * @param encryptKey
         *            加密密钥
         * @return 加密后的base 64 code
         * @throws Exception
         */
        public static String aesEncrypt(String content, String encryptKey)
                throws Exception {
            return base64Encode(aesEncryptToBytes(content, encryptKey));
        }
    
        /**
         * AES解密
         * 
         * @param encryptBytes
         *            待解密的byte[]
         * @param decryptKey
         *            解密密钥
         * @return 解密后的String
         * @throws Exception
         */
        public static String aesDecryptByBytes(byte[] encryptBytes,
                String decryptKey) throws Exception {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            kgen.init(128);
    
            Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
            cipher.init(Cipher.DECRYPT_MODE,
                    new SecretKeySpec(decryptKey.getBytes(), "AES"));
            byte[] decryptBytes = cipher.doFinal(encryptBytes);
    
            return new String(decryptBytes);
        }
    
        /**
         * 将base 64 code AES解密
         * 
         * @param encryptStr
         *            待解密的base 64 code
         * @param decryptKey
         *            解密密钥
         * @return 解密后的string
         * @throws Exception
         */
        public static String aesDecrypt(String encryptStr, String decryptKey)
                throws Exception {
            return StringUtil.isEmpty(encryptStr) ? null : aesDecryptByBytes(
                    base64Decode(encryptStr), decryptKey);
        }
    
    public static void main(String[] args) throws Exception {
            String content = "123456";
            System.out.println("加密前:" + content);
    
            String encrypt = aesEncrypt(content, KEY);
            System.out.println("加密后:" + encrypt);
    
            String decrypt = aesDecrypt(encrypt, KEY);
            System.out.println("解密后:" + decrypt);
        }

    5、小结

    上面说到对称加密和非对称加密各有优缺点,前者效率高,但密钥不安全;后者安全但加密解密时间较长。

    实践中比较常用的做法是,采用非对称加密算法管理对称算法的密钥,然后用对称加密算法加密数据,这样我们就集成了两类加密算法的优点,既实现了加密速度快的优点,又实现了安全方便管理密钥的优点。

  • 相关阅读:
    根据W3C总结Ajax基础技术
    MVC中ActionName标记属性的用法
    为什么做网站一般不用服务端控件?
    Jquery两个比较常用的方法each和data
    MVC中的路由
    SQL中获取刚插入记录时对应的自增列的值
    第一个文章,今天比较兴奋啊! 给大家一个关于SQL复合查询的文章(动态生成多个where条件)
    获取 汉字的首字母(例如张三返回zs)核心方法chinesecap()
    ASP.NET中判断密码的安全度(低,中,高)
    C# 关于密码加密 (转载)
  • 原文地址:https://www.cnblogs.com/saixing/p/6782826.html
Copyright © 2020-2023  润新知