精华内容
下载资源
问答
  • AES 加密 128

    千次阅读 2017-07-04 14:32:21
    AES可以使用128、192、和256位密钥,并且用128位分组加密和解密数据。本文就简单介绍如何通过JAVA实现AES加密。  java实现 加密 /** * 加密 * * @param content * @param encryptKey */ public ...

    论述

      AES已经变成目前对称加密中最流行算法之一;AES可以使用128、192、和256位密钥,并且用128位分组加密和解密数据。本文就简单介绍如何通过JAVA实现AES加密。

     java实现

    加密

    /**
     * 加密
     *
     * @param content
     * @param encryptKey
     */
    
    public static String aesEncrypt(String content, String encryptKey) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        return base64Encode(aesEncryptToBytes(content, encryptKey));
    }
    public static byte[] aesEncryptToBytes(String content, String encryptKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128, new SecureRandom(encryptKey.getBytes()));
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));
        return cipher.doFinal(content.getBytes("UTF-8"));
    }
    public static String base64Encode(byte[] bytes) {
        return new BASE64Encoder().encode(bytes);
    }

     解密数据

    public static String aesDecrypt(String encryptStr, String decryptKey) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, IOException {
        return isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);
    }
    public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128, new SecureRandom(decryptKey.getBytes()));
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));
        byte[] decryptBytes = cipher.doFinal(encryptBytes);
        return new String(decryptBytes, "UTF-8");
    }
    public static byte[] base64Decode(String base64Code) throws IOException {
        return isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);
    }

    这里少了一段话是判断为空的方法
    /**
     * 判断是否为空
     *
     * @param str
     * @return
     */
    public static boolean isEmpty(String str) {
        if (str == null) {
            return true;
        } else if ("".equals(str.trim())) {
            return true;
        } else {
            return false;
        }
    }
    填写加密数据进行加解密
                String content ="{'amt':'" + "0.01" + "'},{'traceNo':'" + "000415" + "'}";
                System.out.println("原文:"+content);
                String encodeContent = aesEncrypt(content,"123456789");
    //            System.out.println("密文:"+byteToHexString(encodeContent.getBytes()));
                String decodeContent = aesDecrypt(encodeContent,"123456789");
                System.out.println("解密:"+decodeContent);
    如果加密数据想看十六进制写了转化类
    public static String byteToHexString(byte [] byteHex){
        String strHex="";
        if(byteHex==null)
            return "";
        for(int i=0;i<byteHex.length;i++){
            strHex=strHex+String.format("%02X", byteHex[i]);
        }
        return strHex;
    }

     
    展开全文
  • SecretKeySpec secretKeySpec = new SecretKeySpec(encodedBytes, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); byte[] result = cipher.doFinal...
    package org.jimmy.autosearch2019.test;
    
    import java.security.SecureRandom;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    
    public class TestAes2019052801 {
    
        public static void main(String[] args) {
            try {
                String content = "123456";
                String secretKey = "123456";
                byte[] encryptedContentBytes = encrypt(content, secretKey);
                String encryptedContent = parseBinaryToHexStr(encryptedContentBytes);
                System.out.println("加密前的文本:" + content);
                System.out.println("加密后的文本:" + encryptedContent);
                byte[] encryptedContentToBinaryStr = parseHexToBinaryStr(encryptedContent);
                byte[] decryptedContentBytes = decrypt(encryptedContentToBinaryStr, secretKey);
                String decryptedContent = new String(decryptedContentBytes);
                System.out.println("解密后的文本:" + decryptedContent);
            } catch(Exception e) { 
                e.printStackTrace();
            }
        }
        
        /**
         * @author ラピスラズリ(Dawn)
         * @date 2019年5月28日 下午2:56:42
         * @detail 16进制字符串转换2进制字符串
         */
        public static byte[] parseHexToBinaryStr(String hexStr) throws Exception {
            byte[] bytes = null;
            if(hexStr.length() < 1) {
                return bytes;
            }
            bytes = new byte[hexStr.length() / 2];
            for(int i = 0; i < hexStr.length() / 2; i++) {
                int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
                int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
                bytes[i] = (byte) (high * 16 + low);
            }
            return bytes;
        }
        
        /**
         * @author ラピスラズリ(Dawn)
         * @date 2019年5月28日 下午2:54:56
         * @detail 2进制字符串转换16进制字符串
         */
        public static String parseBinaryToHexStr(byte[] bytes) throws Exception {
            StringBuffer sb = new StringBuffer();
            for(int i = 0; i < bytes.length; i++) {
                String hex = Integer.toHexString(bytes[i] & 0xff);
                if(hex.length() == 1) {
                    hex = "0" + hex;
                }
                sb.append(hex.toUpperCase());
            }
            return sb.toString();
        }
        
        /**
         * @author ラピスラズリ(Dawn)
         * @date 2019年5月28日 下午3:30:33
         * @detail 解密
         */
        public static byte[] decrypt(byte[] content, String secretKey) throws Exception {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(128, new SecureRandom(secretKey.getBytes()));
            SecretKey generatedSecretKey = keyGenerator.generateKey();
            byte[] encodedBytes = generatedSecretKey.getEncoded();
            SecretKeySpec secretKeySpec = new SecretKeySpec(encodedBytes, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            byte[] result = cipher.doFinal(content);  
            return result;
        }
        
        /**
         * @author ラピスラズリ(Dawn)
         * @date 2019年5月28日 下午2:55:25
         * @detail aes加密
         */
        public static byte[] encrypt(String content, String secretKey) throws Exception {
            // 创建AES的Key生产者
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            // 利用用户密码作为随机数初始化出
            // 128位的key生产者
            //加密没关系,SecureRandom是生成安全随机数序列,password.getBytes()是种子,
            //只要种子相同,序列就一样,所以解密只要有password就行
            keyGenerator.init(128, new SecureRandom(secretKey.getBytes()));
            // 根据用户密码,生成一个密钥
            SecretKey generatedSecretKey = keyGenerator.generateKey();
            // 返回基本编码格式的密钥,如果此密钥不支持编码,则返回
            byte[] encodedBytes = generatedSecretKey.getEncoded();
            // 转换为AES专用密钥
            SecretKeySpec secretKeySpec = new SecretKeySpec(encodedBytes, "AES");
            // 创建密码器
            Cipher cipher = Cipher.getInstance("AES");
            byte[] contentBytes = content.getBytes("utf-8");
            // 初始化为加密模式的密码器
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            //加密
            byte[] result = cipher.doFinal(contentBytes);
            return result;
        }
    
    }

     

    展开全文
  • 在接口测试中,会遇到加密的请求数据,例如:常用的base64加密,AES加密,在这里,简述用Python转化AES的加密方法 原理 官网链接:https://pycryptodome.readthedocs.io/en/latest/src/cipher/aes.html 在线加密/...

    在接口测试中,会遇到加密的请求数据,例如:常用的base64加密,AES加密,在这里,简述用Python转化AES的加密方法

    原理

    • 官网链接:https://pycryptodome.readthedocs.io/en/latest/src/cipher/aes.html
    • 在线加密/解密:https://www.sojson.com/encrypt_aes.html
    • AES加密主要包括两个步骤:密钥扩展和明文加密。
      密钥扩展:将输入的密钥(16字节、24字节和32字节)进行扩展,根据密钥长度的不同,得到扩展后的密钥进行加密的轮数也不相同,个人理解为补码。
    •   例如:对用户名进行AES加密,6位的用户名不满足16个字节,就需要补充位数。
      


    Python实现:Crypto算法库

    算法库详解: https://segmentfault.com/a/1190000016851912

    安装
    Crypto不是自带的模块,需要下载。http://www.voidspace.org.uk/python/modules.shtml#pycrypto

    安装好引用的时候,提示找不到Crypto,找了很多资料,原因是
    C:\Python27\Lib\site-packages在这个路径下面有一个文件夹叫做crypto,把它的首字母改成大写,即是Crypto
    就没有问题了

    简单使用

    from Crypto.Cipher import AES 
    import base64 
    secret = "12345678912345678912345678912345"   #由用户输入的16位或24位或32位长的初始密码字符串 
    cipher = AES.new(secret)            #通过AES处理初始密码字符串,并返回cipher对象 
    s = cipher.encrypt("1234567891234567")     #输入需要加密的字符串,注意字符串长度要是16的倍数。16,32,48.. 
    print s                     #输出加密后的字符串 
    print base64.b64encode(s)            #输出加密后的字符串的base64编码。 
    print cipher.decrypt(s)             #解密
    

    接口自动化中实现

    class AesMethod:
        def __init__(self):
            self.key=key
        def pkcs7padding(self,text):
            """
            明文使用PKCS7填充,如果块长度是16,数据长度9,那么还差7个字节,就在后面补充7个0x07
            数据:  FF FF FF FF FF FF FF FF FF
            填充后:FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07
            最终调用AES加密方法时,传入的是一个byte数组,要求是16的整数倍,因此需要对明文进行处理
            :param text: 待加密内容(明文)
            :return:填充后的数据
            """
            bs = AES.block_size  # 16
            length = len(text)
            bytes_length = len(bytes(text, encoding='utf-8'))
            # tips:utf-8编码时,英文占1个byte,而中文占3个byte
            padding_size = length if(bytes_length == length) else bytes_length
            padding = bs - padding_size % bs
            # tips:chr(padding)看与其它语言的约定,有的会使用'\0'
            padding_text = chr(padding) * padding
            return text + padding_text
    
        def aes_encrypt(self, data):
            key_bytes=bytes(self.key, encoding='utf-8')
            cipher = AES.new(key_bytes,mode=1)
            # 处理明文
            content_padding = self.pkcs7padding(data)
            # 加密
            encrypt_bytes = cipher.encrypt(bytes(content_padding, encoding='utf-8'))
            # 重新编码
            result = str(base64.b64encode(encrypt_bytes), encoding='utf-8')
            return result
    
    
    展开全文
  • STM32利用AES加密数据、解密数据

    千次阅读 2020-05-30 10:33:46
    #define AES_KEY_LENGTH 128 // 加解密模式 #define AES_MODE_ECB 0 // 电子密码本模式(一般模式) #define AES_MODE_CBC 1 // 密码分组链接模式 #define AES_MODE AES_MODE_CBC ///////////////////////...

    一、头文件

    #ifndef _AES_H
    #define _AES_H
    
    
    // 以bit为单位的密钥长度,只能为 128,192 和 256 三种
    #define AES_KEY_LENGTH	128
    
    // 加解密模式
    #define AES_MODE_ECB	0				// 电子密码本模式(一般模式)
    #define AES_MODE_CBC	1				// 密码分组链接模式
    #define AES_MODE		AES_MODE_CBC
    
    
    ///
    //	函数名:	aes_init
    //	描述:		初始化,在此执行扩展密钥操作。
    //	输入参数:	pKey -- 原始密钥,其长度必须为 AES_KEY_LENGTH/8 字节。
    //	输出参数:	无。
    //	返回值:	无。
    ///
    void aes_init(const void *pKey);
    
    //
    //	函数名:	aes_encrypt
    //	描述:		加密数据
    //	输入参数:	pPlainText	-- 明文,即需加密的数据,其长度为nDataLen字节。
    //				nDataLen	-- 数据长度,以字节为单位,必须为AES_KEY_LENGTH/8的整倍数。
    //				pIV			-- 初始化向量,如果使用ECB模式,可设为NULL。
    //	输出参数:	pCipherText	-- 密文,即由明文加密后的数据,可以与pPlainText相同。
    //	返回值:	无。
    //
    void aes_encrypt(const unsigned char *pPlainText, unsigned char *pCipherText, 
    				 unsigned int nDataLen, const unsigned char *pIV);
    
    //
    //	函数名:	aes_decrypt
    //	描述:		解密数据
    //	输入参数:	pCipherText -- 密文,即需解密的数据,其长度为nDataLen字节。
    //				nDataLen	-- 数据长度,以字节为单位,必须为AES_KEY_LENGTH/8的整倍数。
    //				pIV			-- 初始化向量,如果使用ECB模式,可设为NULL。
    //	输出参数:	pPlainText  -- 明文,即由密文解密后的数据,可以与pCipherText相同。
    //	返回值:	无。
    //
    void aes_decrypt( const unsigned char *pCipherText,unsigned char *pPlainText, 
    				 unsigned int nDataLen, const unsigned char *pIV);
    #endif  /* _AES_H */
    

    二、源文件

    #include "aes.h"
    #include "string.h"
    
        
    // 为了能针对C51进行优化,并且又使代码可用于ARM和PC等环境,
    // 在非C51环境(没有定义__C51__)下需要把C51特定的关键字定义为空
    #ifndef __C51__
    	#define code
    	#define data
    	#define idata
    	#define xdata
    	#define pdata
    	typedef unsigned char BOOL;
    #else
    	typedef bit BOOL;
    #endif
    
    #define Nk	(AES_KEY_LENGTH / 32)		// 以“字”(4字节)为单位的密钥长度
    #define Nb	4							// 以“字”(4字节)为单位的加解密数据块大小,固定为4
    
    // Nr:加密的轮数
    #if   AES_KEY_LENGTH == 128
    	#define Nr	10
    #elif AES_KEY_LENGTH == 192
    	#define Nr	12
    #elif AES_KEY_LENGTH == 256
    	#define Nr	14
    #else
    	#error AES_KEY_LENGTH must be 128, 192 or 256 BOOLs!
    #endif
    
    // GF(28) 多项式
    #define BPOLY 0x1B // Lower 8 BOOLs of (x^8 + x^4 + x^3 + x + 1), ie. (x^4 + x^3 + x + 1).
    
    /*****************************************************************************
    *  Typedef  Enum                        枚举定义
    *****************************************************************************/
    
    /*****************************************************************************
    *  Struct                               数据结构定义
    ******************************************************************************/
    
    
    /*****************************************************************************
    *  Local variable                       局部变量
    *****************************************************************************/
    
    // AES子密钥表,当密钥长度为128位时,占用176字节空间
    static xdata unsigned char g_roundKeyTable[4*Nb*(Nr+1)];
    
    // 加密用的SBox
    static code const unsigned char sBox[256] = 
    {
    	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
    	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
    	0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
    	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
    	0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
    	0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
    	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
    	0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
    	0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
    	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
    	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
    	0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
    	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
    	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
    	0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
    	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 
    };
    
    // 解密用的SBox
    static code const unsigned char invSBox[256] = 
    {
    	0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
    	0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
    	0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
    	0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
    	0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
    	0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
    	0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
    	0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
    	0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
    	0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
    	0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
    	0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
    	0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
    	0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
    	0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
    	0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d	
    };
    
    
    ///
    //	函数名:	rotation_word
    //	描述:		对一个“字”数据进行循环右移。
    //	输入参数:	pWord -- 要右移的4字节数据。
    //	输出参数:	pWord -- 右移后的4字节数据。
    //	返回值:	无。
    ///
    static void rotation_word(unsigned char *pWord)
    {
    	unsigned char temp = pWord[0];
    	pWord[0]  = pWord[1];
    	pWord[1]  = pWord[2];
    	pWord[2]  = pWord[3];
    	pWord[3]  = temp;
    }
    
    ///
    //	函数名:	xor_bytes
    //	描述:		批量异或两组数据。
    //	输入参数:	pData1 -- 要异或的第一组数据。
    //				pData1 -- 要异或的第二组数据。
    //				nCount -- 要异或的数据长度。
    //	输出参数:	pData1 -- 异或后的结果。
    //	返回值:	无。
    ///
    static void xor_bytes(unsigned char *pData1, const unsigned char *pData2, unsigned char nCount)
    {
    	unsigned char i;
    	
    	for (i = 0; i < nCount; i++)
    	{
    		pData1[i] ^= pData2[i];
    	}
    }
    
    ///
    //	函数名:	AddRoundKey
    //	描述:		把 中间状态数据 加上(异或)子密钥,数据长度为16字节。
    //	输入参数:	pState	  -- 状态数据。
    //				pRoundKey -- 子密钥数据。
    //	输出参数:	pState	  -- 加上子密钥后的状态数据。
    //	返回值:	无。
    ///
    // static void AddRoundKey(unsigned char *pState, const unsigned char *pRoundKey)
    // {
    // 	xor_bytes(pState, pRoundKey, 4*Nb);
    // }
    
    // AddRoundKey的宏形式,比函数形式可以节省4字节的data数据
    #define AddRoundKey(pState, pRoundKey) \
    	xor_bytes((pState), (pRoundKey), 4*Nb)
    
    
    ///
    //	函数名:	sub_bytes
    //	描述:		通过S盒子置换状态数据。
    //	输入参数:	pState	-- 状态数据。
    //				nCount  -- 状态数据长度。
    //				bInvert	-- 是否使用反向S盒子(解密时使用)。
    //	输出参数:	pState	-- 置换后的状态数据。
    //	返回值:	无。
    ///
    static void sub_bytes(unsigned char *pState, unsigned char nCount, BOOL bInvert)
    {
    	unsigned char i;
    	const unsigned char code *pSBox = bInvert ? invSBox : sBox;
    	
    	for (i = 0; i < nCount; i++)
    	{
    		pState[i] = pSBox[pState[i]];
    	}
    }
    
    ///
    //	函数名:	shift_rows
    //	描述:		把状态数据移行。
    //	输入参数:	pState	-- 状态数据。
    //				bInvert	-- 是否反向移行(解密时使用)。
    //	输出参数:	pState	-- 移行后的状态数据。
    //	返回值:	无。
    ///
    static void shift_rows(unsigned char *pState, BOOL bInvert)
    {
    	// 注意:状态数据以列形式存放!
    
    	unsigned char r;	// row,   行
    	unsigned char c;	// column,列
    	unsigned char temp;
    	unsigned char rowData[4];
    	
    	for (r = 1; r < 4; r++)
    	{
    		// 备份一行数据
    		for (c = 0; c < 4; c++)
    		{
    			rowData[c] = pState[r + 4*c];
    		}
    		
    		temp = bInvert ? (4 - r) : r;
    		for (c = 0; c < 4; c++)
    		{
    			pState[r + 4*c] = rowData[(c + temp) % 4];
    		}
    	}
    }
    
    ///
    //	函数名:	gf_mult_by02
    //	描述:		在GF(28)域的 乘2 运算。
    //	输入参数:	num	-- 乘数。
    //	输出参数:	无。
    //	返回值:	num乘以2的结果。
    ///
    static unsigned char gf_mult_by02(unsigned char num)
    {
    	if ((num & 0x80) == 0)
    	{
    		num = num << 1;
    	}
    	else
    	{
    		num = (num << 1) ^ BPOLY;
    	}
    	
    	return num;
    }
    
    ///
    //	函数名:	mix_columns
    //	描述:		混合状态各列数据。
    //	输入参数:	pState	-- 状态数据。
    //				bInvert	-- 是否反向混合(解密时使用)。
    //	输出参数:	pState	-- 混合列后的状态数据。
    //	返回值:	无。
    ///
    static void mix_columns(unsigned char *pState, BOOL bInvert)
    {
    	unsigned char i;
    	unsigned char temp;
    	unsigned char a0Pa2_M4;	// 4(a0 + a2)
    	unsigned char a1Pa3_M4;	// 4(a1 + a3)
    	unsigned char result[4];
    
    	for (i = 0; i < 4; i++, pState += 4)
    	{
    		// b0 = 2a0 + 3a1 + a2 + a3 
    		//    = (a0 + a1 + a2 + a3) + 2(a0 + a1) + a0
    
    		temp = pState[0] ^ pState[1] ^ pState[2] ^ pState[3];
    		result[0] = temp ^ pState[0] ^ gf_mult_by02((unsigned char) (pState[0] ^ pState[1]));
    		result[1] = temp ^ pState[1] ^ gf_mult_by02((unsigned char) (pState[1] ^ pState[2]));
    		result[2] = temp ^ pState[2] ^ gf_mult_by02((unsigned char) (pState[2] ^ pState[3]));
    		result[3] = temp ^ pState[3] ^ gf_mult_by02((unsigned char) (pState[3] ^ pState[0]));
    
    		if (bInvert)
    		{
    		// b0' = 14a0 + 11a1 + 13a2 + 9a3 
    		//     = (a0 + a1 + a2 + a3) + 2(a0 + a1) + a0	(这部分为b0)
    		//       + 2(4(a0 + a2) + 4(a1 + a3))
    		//       +   4(a0 + a2)
    
    			a0Pa2_M4 = gf_mult_by02(gf_mult_by02((unsigned char) (pState[0] ^ pState[2])));
    			a1Pa3_M4 = gf_mult_by02(gf_mult_by02((unsigned char) (pState[1] ^ pState[3])));
    			temp	 = gf_mult_by02((unsigned char) (a0Pa2_M4 ^ a1Pa3_M4));
    			result[0] ^= temp ^ a0Pa2_M4;
    			result[1] ^= temp ^ a1Pa3_M4;
    			result[2] ^= temp ^ a0Pa2_M4;
    			result[3] ^= temp ^ a1Pa3_M4;
    		}
    
    		memcpy(pState, result, 4);
    	}
    }
    
    ///
    //	函数名:	block_encrypt
    //	描述:		对单块数据加密。
    //	输入参数:	pState -- 状态数据。
    //	输出参数:	pState -- 加密后的状态数据。
    //	返回值:	无。
    ///
    static void block_encrypt(unsigned char *pState)
    {
    	unsigned char i;
    	
    	AddRoundKey(pState, g_roundKeyTable);
    	
    	for (i = 1; i <= Nr; i++)	// i = [1, Nr]
    	{
    		sub_bytes(pState, 4*Nb, 0);
    		shift_rows(pState, 0);
    
    		if (i != Nr)
    		{
    			mix_columns(pState, 0);
    		}
    
    		AddRoundKey(pState, &g_roundKeyTable[4*Nb*i]);
    	}
    	
    // 为了节省代码,合并到循化执行
    // 	sub_bytes(pState, 4*Nb);
    //	shift_rows(pState, 0);
    // 	AddRoundKey(pState, &g_roundKeyTable[4*Nb*Nr]);
    }
    
    ///
    //	函数名:	block_decrypt
    //	描述:		对单块数据解密。
    //	输入参数:	pState -- 状态数据。
    //	输出参数:	pState -- 解密后的状态数据。
    //	返回值:	无。
    ///
    static void block_decrypt(unsigned char *pState)
    {
    	unsigned char i;
    	
    	AddRoundKey(pState, &g_roundKeyTable[4*Nb*Nr]);
    	
    	for (i = Nr; i > 0; i--)	// i = [Nr, 1]
    	{
    		shift_rows(pState, 1);
    		sub_bytes(pState, 4*Nb, 1);
    		AddRoundKey(pState, &g_roundKeyTable[4*Nb*(i-1)]);
    
    		if (i != 1)
    		{
    			mix_columns(pState, 1);
    		}
    	}
    	
    // 为了节省代码,合并到循化执行
    //  shift_rows(pState, 1);
    //  sub_bytes(pState, 4*Nb, 1);
    //  AddRoundKey(pState, g_roundKeyTable);
    }
    
    /*****************************************************************************
    *  Global Functions                     全局函数
    ******************************************************************************/
    
    
    ///
    //	函数名:	aes_init
    //	描述:		初始化,在此执行扩展密钥操作。
    //	输入参数:	pKey -- 原始密钥,其长度必须为 AES_KEY_LENGTH/8 字节。
    //	输出参数:	无。
    //	返回值:	无。
    ///
    void aes_init(const void *pKey)
    {
    	// 扩展密钥
    	unsigned char i;
    	unsigned char *pRoundKey;
    	unsigned char Rcon[4] = {0x01, 0x00, 0x00, 0x00};
    
    	memcpy(g_roundKeyTable, pKey, 4*Nk);
    
    	pRoundKey = &g_roundKeyTable[4*Nk];
    
    	for (i = Nk; i < Nb*(Nr+1); pRoundKey += 4, i++)
    	{
    		memcpy(pRoundKey, pRoundKey - 4, 4);
    
    		if (i % Nk == 0)
    		{
    			rotation_word(pRoundKey);
    			sub_bytes(pRoundKey, 4, 0);
    			xor_bytes(pRoundKey, Rcon, 4);
    
    			Rcon[0] = gf_mult_by02(Rcon[0]);
    		}
    		else if (Nk > 6 && i % Nk == Nb)
    		{
    			sub_bytes(pRoundKey, 4, 0);
    		}
    
    		xor_bytes(pRoundKey, pRoundKey - 4*Nk, 4);
    	}
    }
    
    //
    //	函数名:	aes_encrypt
    //	描述:		加密数据
    //	输入参数:	pPlainText	-- 明文,即需加密的数据,其长度为nDataLen字节。
    //				nDataLen	-- 数据长度,以字节为单位,必须为AES_KEY_LENGTH/8的整倍数。
    //				pIV			-- 初始化向量,如果使用ECB模式,可设为NULL。
    //	输出参数:	pCipherText	-- 密文,即由明文加密后的数据,可以与pPlainText相同。
    //	返回值:	无。
    //
    void aes_encrypt(const unsigned char *pPlainText, unsigned char *pCipherText, 
    				 unsigned int nDataLen, const unsigned char *pIV)
    {
    	unsigned int i;
    
    	if (pPlainText != pCipherText)
    	{
    		memcpy(pCipherText, pPlainText, nDataLen);
    	}
    
    	for (i = nDataLen/(4*Nb); i > 0 ; i--, pCipherText += 4*Nb)
    	{
    		#if AES_MODE == AES_MODE_CBC
    			xor_bytes(pCipherText, pIV, 4*Nb);
    		#endif
    
    		block_encrypt(pCipherText);
    		pIV = pCipherText;
    	}
    }
    
    //
    //	函数名:	aes_decrypt
    //	描述:		解密数据
    //	输入参数:	pCipherText -- 密文,即需解密的数据,其长度为nDataLen字节。
    //				nDataLen	-- 数据长度,以字节为单位,必须为AES_KEY_LENGTH/8的整倍数。
    //				pIV			-- 初始化向量,如果使用ECB模式,可设为NULL。
    //	输出参数:	pPlainText  -- 明文,即由密文解密后的数据,可以与pCipherText相同。
    //	返回值:	无。
    //
    void aes_decrypt( const unsigned char *pCipherText,unsigned char *pPlainText, 
    				 unsigned int nDataLen, const unsigned char *pIV)
    {
    	unsigned int i;
    
    	if (pPlainText != pCipherText)
    	{
    		memcpy(pPlainText, pCipherText, nDataLen);
    	}
    
    	// 从最后一块数据开始解密,这样不用开辟空间来保存IV
    	pPlainText += nDataLen - 4*Nb;
    	for (i = nDataLen/(4*Nb); i > 0 ; i--, pPlainText -= 4*Nb)
    	{
    		block_decrypt(pPlainText);
    
    		#if AES_MODE == AES_MODE_CBC
    			if (i == 1)
    			{// 最后一块数据
    				xor_bytes(pPlainText, pIV, 4*Nb);
    			}
    			else
    			{
    				xor_bytes(pPlainText, pPlainText - 4*Nb, 4*Nb);
    			}
    		#endif
    	}
    }
    

    三、使用
    使用注意点:
    1、AES_KEY_LENGTH取值只能是128,192 和 256
    2、密钥和向量表长度为AES_KEY_LENGTH/8个字节
    3、加密、解密数据长度为AES_KEY_LENGTH/8的整数倍字节

    
    int main(void)
    { 
    	u8 buf[16],saveBuf[16],descryptBuf[16];
    	u16 i;
    	unsigned char AES128key[16] = "123456789abcdefa";//秘钥
    	unsigned char AES_IV[16]= "0102030405123456";//向量表
    	delay_init(168);		  //初始化延时函数
    	LED_Init();		        //初始化LED端口
    
    	aes_init(AES128key);//AES初始化
    	
    	for(i=0;i<sizeof(buf);i++)
    	{
    		buf[i]=i;
    	}
    	while(1)
    	{
    		aes_encrypt(buf,saveBuf,sizeof(buf), AES_IV);
    		
    		
    		aes_decrypt(saveBuf,descryptBuf, sizeof(buf), AES_IV);
    		
    		
    		GPIO_ResetBits(GPIOF,GPIO_Pin_9);  //LED0对应引脚GPIOF.9拉低,亮  等同LED0=0;
    		GPIO_SetBits(GPIOF,GPIO_Pin_10);   //LED1对应引脚GPIOF.10拉高,灭 等同LED1=1;
    		delay_ms(500);  		   //延时300ms
    		GPIO_SetBits(GPIOF,GPIO_Pin_9);	   //LED0对应引脚GPIOF.0拉高,灭  等同LED0=1;
    		GPIO_ResetBits(GPIOF,GPIO_Pin_10); //LED1对应引脚GPIOF.10拉低,亮 等同LED1=0;
    		delay_ms(500);                     //延时300ms
    	}
    }
    

    源代码地址

    展开全文
  • AES128 加密 解密 C#

    热门讨论 2013-01-04 15:36:24
    AES128 加密 解密 C#实现 可以实现文件等的加密解密。
  • AESUtils实现了基于AES的ECB模式,选用了zeropadding填充,数据位为128 加上密码去加解密数据,优化并实测通过
  • AES算法简介 AES是一种对称加密算法,或称分组对称加密算法。...AES加密数据块分组长度必须为128比特(bit位),密钥长度可以是128比特、192比特、256比特中的任意一个(如果数据块及密钥长度不足...
  • 使用AES加密 本文使用 "AES/CBC/PKCS5Padding" CBC模式需用到两个公钥 ...public class AES128utils { // public static final String AES128_KEY="kabuke1yc1881cn1"; /** * 加密
  • AES简介 1.AES是一种区块加密标准算法,它的提出...2.AES最常见的有3种方案,分别是AES-128AES-192和AES-256,它们的区别在于密钥长度不同,AES-128的密钥长度为16bytes(128bit / 8),后两者分别为24bytes和32byte
  • 该算法不是为提高速度而构建的,并且不包含文本消息或数据输入的128位输入。 Cipher 和 InvCipher 是要执行的主要函数。 函数根据密钥大小执行 AES128AES192 或 AES256。 函数不会检查密钥大小或输入的长度...
  • 需要配置AES_MODE(模式和填充)、AES_KEY(密钥)、AES_IV(偏移量) 至于是128还是192还是256,是根据密钥的长度自动确定的,且密钥长度只有三种:16、24、32 128的16位key,16位iv 192的24位key,16位iv 256的32...
  • AES

    2020-11-19 11:28:28
    AES是一种区块加密标准算法,它的...AES最常见的有3种方案,分别是AES-128AES-192和AES-256,它们的区别在于密钥长度不同,AES-128的密钥长度为16bytes(128bit / 8),后两者分别为24bytes和32bytes。密钥越长,安全
  • c++使用openssl库实现RSA、AES数据加密

    千次阅读 2017-06-22 10:02:42
    使用openssl库实现RSA、AES数据加密  openssl是可以很方便加密解密的库,可以使用它来对需要在网络中传输的数据加密。可以使用非对称加密:公钥加密,私钥解密。openssl提供了对RSA的支持,但RSA存在计算效率...
  • Java中使用AES加密数据

    2018-09-06 19:37:23
    1. 加密和解密方法  @Slf4j public class AESUtils { ... * AES加密 * * @param key 密钥 * @param iv 偏移量 * @param data 需要加密的数据 */ public static byte[] encrypt(String key, St...
  • 对于CTR,CCM,CMAC,GCM等加密模式,将永远不会使用AES内核中的解密功能,因此可以删除解密处理。 这是一个相当紧凑的实现。 仅拥有一个S盒就可以实现进一步的降低。 类似地,可以通过具有8个或什至1
  • C#实现AES加密解密(AES-128-CBC)

    千次阅读 2014-12-11 16:30:00
    AES算法描述简介:DES数据加密标准算法由于密钥长度较小(56位),已经不适应当今分布式开放网络对数据加密安全性的要求,因此1997年NIST公开征集新的数据加密标准,即AES。经过三轮的筛选,比利时Joan Daeman和Vincent ...
  • 使用crypto++ AES 加密一个16 字节(128bit)的数据,想得到一个16字节的密文, 这里我使用的是crypto++ CBC模式, 发现加密后得到的是一个32个字节的密文,请问我要实现这个加密16字节得到16字节长度密文应该怎么做...
  • openssl的AES128加密总结

    千次阅读 2018-01-05 17:02:49
    3.每一个明文利用AES加密器和密钥,加密成密文。 4.拼接所有的密文,成为最终的密文结果。 AES支持三种长度的密钥: 128位,192位,256位 填充方式: NoPadding: 不做任何填充,但是要求明文必须是16...
  • AES128   {   private static final String UTF_8 = "UTF-8";       /**   * 加密   * @param content 需要...
  • AES数据进行加密与解密随着对称密码的发展,DES数据加密标准算法由于密钥长度较小(56位),已经不适应当今分布式开放网络对数据加密安全性的要求,因此1997年NIST公开征集新的数据加密标准,即AES[1]。经过三轮的筛选,...
  • 程序在本地调试,接收数据,解密数据,都没问题,在linux运行,接收数据抛出异常,判断是程序走到解密类,抛出此异常,该怎么处理次异常 java.security.NoSuchAlgorithmException: Cannot find any provider supporting AES/...
  • 使用openssl库实现RSA、AES数据加密

    千次阅读 2015-07-15 21:27:45
    openssl是可以很方便加密解密的库,可以使用它来对需要在网络中传输的数据加密。可以使用非对称加密:公钥加密,私钥解密。openssl提供了对RSA的支持,但RSA存在计算效率低的问题,所以一般的做法是使用对称密钥加密...
  • 低功耗蓝牙BLE之AES-128加密算法

    万次阅读 2016-06-22 17:23:39
    低功耗蓝牙中的所有加密和认证都基于同一个加密引擎,称为高级加密系统(AES

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,780
精华内容 6,712
关键字:

aes数据块128