美文网首页数据结构与算法
加密算法(三:AES算法)

加密算法(三:AES算法)

作者: 腊鸡程序员 | 来源:发表于2019-04-16 17:57 被阅读0次
    timg (5).jpg
    简介

    https连接支付宝,靠AES进行保护
    是一种区块加密技术,把原文分成128位每块的数据,对每块单独进行加密

    https传输中的加密:
    密钥交换算法,用于决定客户端与服务器之间在握手的过程中如何认证,用到的算法包括RSA,Diffie-Hellman,ECDH,PSK等

    加密算法,用于加密消息流,该名称后通常会带有两个数字,分别表示密钥的长度和初始向量的长度,比如DES 56/56, RC2 56/128, RC4 128/128, AES 128/128, AES 256/256

    报文认证信息码(MAC)算法,用于创建报文摘要,确保消息的完整性(没有被篡改),算法包括MD5,SHA等。

    流程图
    image.png image.png
    算法思路

    加密:

    1. SubBytes(字节替代)


      image.png

    S-BOX

    static uint8_t g_aes_sbox[256] =
    {
    // 0 1 2 3 4 5 6 7 8 9 a b c d e f
    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, // 0
    0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, // 1
    0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, // 2
    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, // 3
    0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, // 4
    0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, // 5
    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, // 6
    0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, // 7
    0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, // 8
    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, // 9
    0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, // a
    0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, // b
    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, // c
    0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, // d
    0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, // e
    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 // f
    };
    在S-BOX中对应找到明文对应位置上的数据,替换明文中的内容
    如:19 在S-BOX中为d4 就用d4替换19原来的位置

    1. ShiftRows(行位移)


      image.png
    2. MixColumns(列混淆)


      image.png
    3. AddRoundKey(轮密钥加)


      image.png
    4. 以上4步完成10轮,即得到密文


      image.png

    解密(密钥扩展):


    image.png
    1. 先把最后一列的第一个移到最下面


      image.png
    2. 进行S-BOX替换

    image.png

    static uint8_t g_aes_invsbox[256] =
    {
    // 0 1 2 3 4 5 6 7 8 9 a b c d e f
    0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, // 0
    0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, // 1
    0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, // 2
    0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, // 3
    0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, // 4
    0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, // 5
    0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, // 6
    0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, // 7
    0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, // 8
    0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, // 9
    0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, // a
    0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, // b
    0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, // c
    0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, // d
    0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, // e
    0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d // f
    };

    1. 把第一列异或上次结果再异或RCON距阵中的第一列,RCON中删除第一列


      image.png
    2. 结果异或第二列
      结果再与第三列异或
      结果再与第四列异或

    image.png
    1. 接下来以最后四列重复执行上面的所有操作,直到RCON用完,即得到明文


      image.png
    代码
    import org.junit.Test;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import java.security.SecureRandom;
    
    public class AES {
    
        //加密方法
        public static String ALGORITHM = "AES";
    
        //加密
        public static byte[] encrype(String content, String password) throws Exception {
            //创建AES的key生产者
            KeyGenerator kgen = KeyGenerator.getInstance(ALGORITHM);
            //利用用户密码作为随机数初始化
            kgen.init(128, new SecureRandom(password.getBytes()));
            //根据用户密码,生成一个秘钥,所有对称算法通用
            SecretKey secretKey = kgen.generateKey();
            //对秘钥进行基本编码
            byte[] encodeFormat = secretKey.getEncoded();
            //转换成AES专用的秘钥 RoundKey
            SecretKeySpec key = new SecretKeySpec(encodeFormat, ALGORITHM);
            //创建一个密码器
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            //开始加密
            byte[] bytecontent = content.getBytes();
            //初始化为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, key);
            //加密
            byte[] result = cipher.doFinal(bytecontent);
            //如果数据较多,就先用cipher.update(),再用cipher.doFinal()
            return result;
        }
    
        /**
         * 解密
         *
         * @param content  密文
         * @param password 用户密码
         * @return
         * @throws Exception
         */
        public static byte[] decrypt(byte[] content, String password) throws Exception {
            //创建AES的key生产者
            KeyGenerator kgen = KeyGenerator.getInstance(ALGORITHM);
            //利用用户密码作为随机数初始化
            kgen.init(128, new SecureRandom(password.getBytes()));
            //根据用户密码生成一个秘钥,所有对称算法通用
            SecretKey secretKey = kgen.generateKey();
            //对密码进行基本的编码
            byte[] encodeFormate = secretKey.getEncoded();
            //生成AES算法专用的密码
            SecretKeySpec key = new SecretKeySpec(encodeFormate, ALGORITHM);
            //创建一个密码器
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, key);
            //解密
            byte[] result = cipher.doFinal(content);
            return result;
        }
    
        @Test
        public void test() throws Exception {
            String content = "jett1231eqwdsafsadadfwq23123";
            String password = "123456";
            System.out.println("加密前:" + content);
    
            //加密
            byte[] encrypt = encrype(content, password);
            System.out.println("加密后:" + new String(encrypt));
    
            //解密
            byte[] decrypt = decrypt(encrypt, password);
            System.out.println("解密后:" + new String(decrypt));
        }
    }
    
    
    通用应用方案

    实际中,一般是通过RSA加密AES的密钥,传输到接收方,接收方解密得到AES密钥,然后发送方和接收方用AES密钥来通信。

    JDK的支持
    MessageDigest 单向加密
    KeyGenerator 对称
    KeyPairGenerator 非对称

    相关文章

      网友评论

        本文标题:加密算法(三:AES算法)

        本文链接:https://www.haomeiwen.com/subject/schiwqtx.html