zoukankan      html  css  js  c++  java
  • 小谈加密算法

    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、小结

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

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

  • 相关阅读:
    [ERR] Node 10.211.55.8:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
    PAT A1137 Final Grading (25 分)——排序
    PAT A1136 A Delayed Palindrome (20 分)——回文,大整数
    PAT A1134 Vertex Cover (25 分)——图遍历
    PAT A1133 Splitting A Linked List (25 分)——链表
    PAT A1132 Cut Integer (20 分)——数学题
    PAT A1130 Infix Expression (25 分)——中序遍历
    PAT A1142 Maximal Clique (25 分)——图
    PAT A1141 PAT Ranking of Institutions (25 分)——排序,结构体初始化
    PAT A1140 Look-and-say Sequence (20 分)——数学题
  • 原文地址:https://www.cnblogs.com/saixing/p/6730186.html
Copyright © 2011-2022 走看看