• linux以下C 利用openssl的AES库加密,解密


    OpenSSL提供了AES加解密算法的API


    const char *AES_options(void);

    AES算法状态,是所有支持或者是部分支持。

    返回值:“aes(full)” 或者"aes(partial)"


    int AES_set_encrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key);

    设定加密用的Key;

    userKey: 密钥数值。

    bits:密钥长度,以bit为单位。假设密钥数字是16个字节,则此參数值应为128。

    key: AES_KEY对象指针;

    返回值: 0 成功, -1 userkey,key为空, -2: 密钥长度不是128。192。256;


    int AES_set_decrypt_key(const unsigned char *userKey, const int bits,  AES_KEY *key);

    设定解密用的Key;

    userKey: 密钥数值;

    bits:密钥长度,以bit为单位,假设密钥数字是16个字节。则此參数值应为128;

    key: AES_KEY对象指针;

    返回值: 0 成功, -1 userkey。key为空。 -2: 密钥长度不是128。192,256。


    void AES_encrypt(const unsigned char *in, unsigned char *out,const AES_KEY *key);

    AES 加密。加密单个数据块。in,out能够是同一内存区;

    in: 须要加密的数据;

    out: 加密后的数据。

    key:AES 密钥。


    void AES_decrypt(const unsigned char *in, unsigned char *out,const AES_KEY *key);

    AES 解密。解密单个数据块,in。out能够是同一内存区;

    in: 须要解密的数据。

    out: 解密后的数据;

    key:AES 密钥。


    void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,    const AES_KEY *key, const int enc);

    AES加密/解密单个数据块,ECB模式

    in: 须要加密/解密的数据;

    out: 计算后输出的数据。

    key:密钥

    enc: AES_ENCRYPT 代表加密, AES_DECRYPT代表解密。


    void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,   size_t length, const AES_KEY *key,    unsigned char *ivec, const int enc);

    AES加密/解密单个数据块,CBC模式

    in: 须要加密/解密的数据;

    out: 计算后输出的数据。

    length: 数据长度

    key:密钥

    ivec: 初始向量

    enc: AES_ENCRYPT 代表加密, AES_DECRYPT代表解密;


    void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
        size_t length, const AES_KEY *key,
        unsigned char *ivec, int *num, const int enc);
    AES CFB128位模式加密/解密。输入输出数据区能够重叠。
    in: 须要加密/解密的数据。
    out: 计算后输出的数据;
    length: 数据长度;
    key: 密钥;
    ivec: 初始化向量
    num: 输出參数。计算状态。多少个CFB数据块
    enc: 计算模式。 加密: AES_ENCRYPT 。 解密: AES_DECRYPT
        
    void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
        size_t length, const AES_KEY *key,
        unsigned char *ivec, int *num, const int enc);
    AES CFB1位模式加密/解密。输入输出数据区能够重叠;
    in: 须要加密/解密的数据;
    out: 计算后输出的数据;
    length: 数据长度;
    key: 密钥;
    ivec: 初始化向量
    num: 输出參数,计算状态,多少个CFB数据块
    enc: 计算模式, 加密: AES_ENCRYPT , 解密: AES_DECRYPT
        
        
    void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
        size_t length, const AES_KEY *key,
        unsigned char *ivec, int *num, const int enc);
    AES CFB8位模式加密/解密。输入输出数据区能够重叠;
    in: 须要加密/解密的数据;
    out: 计算后输出的数据;
    length: 数据长度;
    key: 密钥;
    ivec: 初始化向量
    num: 输出參数,计算状态,多少个CFB数据块
    enc: 计算模式, 加密: AES_ENCRYPT , 解密: AES_DECRYPT

        
    void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
        size_t length, const AES_KEY *key,
        unsigned char *ivec, int *num);
    AES OFB128位模式加密/解密,输入输出数据区能够重叠;
    in: 须要加密/解密的数据;
    out: 计算后输出的数据。
    length: 数据长度;
    key: 密钥。
    ivec: 初始化向量
    num: 输出參数,计算状态,多少个CFB数据块
    enc: 计算模式, 加密: AES_ENCRYPT , 解密: AES_DECRYPT

            
        
    void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
        size_t length, const AES_KEY *key,
        unsigned char ivec[AES_BLOCK_SIZE],
        unsigned char ecount_buf[AES_BLOCK_SIZE],
        unsigned int *num);
    AES CTR128位模式加密/解密,输入输出数据区能够重叠;
    in: 须要加密/解密的数据。
    out: 计算后输出的数据;
    length: 数据长度;
    key: 密钥。
    ivec: 初始化向量
    ecount_buf: 输出參加,加密的次数,在第一次调用此函数时,须要初始化为0
    num: 输出參数,计算状态,多少个CFB数据块,在第一次调用此函数时,须要初始化为0
    enc: 计算模式。 加密: AES_ENCRYPT , 解密: AES_DECRYPT



    void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
                 size_t length, const AES_KEY *key,
                 unsigned char *ivec, const int enc);
    AES 加密/解密,输入输出数据区能够重叠,初始化向量是加密数据块的2倍,加密前用前半部分做一次异或。加密后用后半部分做一次异或;
    in: 须要加密/解密的数据;
    out: 计算后输出的数据。
    length: 数据长度;
    key: 密钥;
    ivec: 初始化向量
    enc: 计算模式。 加密: AES_ENCRYPT , 解密: AES_DECRYPT
        
                     

    void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
                size_t length, const AES_KEY *key,
                const AES_KEY *key2, const unsigned char *ivec,
                const int enc);
    AES 加密/解密。输入输出数据区能够重叠。初始化向量是加密数据块的4倍,加密前用第一部分做一次异或。加密后用第二部分做一次异或;
    最后一个加密数据块,加密前用第三部分异或,加密后用第四部分异或;
    in: 须要加密/解密的数据;
    out: 计算后输出的数据;
    length: 数据长度。
    key: 密钥。
    ivec: 初始化向量
    enc: 计算模式, 加密: AES_ENCRYPT , 解密: AES_DECRYPT            

    int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
            unsigned char *out,
            const unsigned char *in, unsigned int inlen)

    用AES算法对明文key数据加密

    key: AES Key,用于加密密钥数据

    iv: 初始化向量

    out: 加密后的密钥数据

    in: 密钥数据

    inlen: 密钥数据长度

    返回值: 1: 成功。 0: 失败


    int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
            unsigned char *out,
            const unsigned char *in, unsigned int inlen)

    用AES算法对明文key数据加密

    key: AES Key,用于加密密钥数据

    iv: 初始化向量

    out: 加密后的密钥数据

    in: 密钥数据

    inlen: 密钥数据长度

    返回值: 1: 成功, 0: 失败


    C实例分析:

    首先要了解AES加密是什么。以及几种加密模式的差别。之后才是编程。

    详细的编程案例,在以下的链接。

    openssl之aes加密(AES_cbc_encrypt 与 AES_encrypt 的编程案例)

    以下这个链接有具体图解。
    http://www.cnblogs.com/adylee/archive/2007/09/14/893438.html
    ECB模式 
      长处: 
      1.简单; 
      2.有利于并行计算。 
      3.误差不会被传送。 
      缺点: 
      1.不能隐藏明文的模式; 
      2.可能对明文进行主动攻击; 
    CBC模式: 
      长处: 
      1.不easy主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。 
      缺点: 
      1.不利于并行计算。 
      2.误差传递。 
      3.须要初始化向量IV 
    CFB模式: 
      长处: 
      1.隐藏了明文模式; 
      2.分组password转化为流模式; 
      3.能够及时加密传送小于分组的数据; 
      缺点: 
      1.不利于并行计算; 
      2.误差传送:一个明文单元损坏影响多个单元; 
      3.唯一的IV; 
    ofb模式: 
      长处: 
      1.隐藏了明文模式; 
      2.分组password转化为流模式; 
      3.能够及时加密传送小于分组的数据; 
      缺点: 
      1.不利于并行计算; 
      2.对明文的主动攻击是可能的; 
      3.误差传送:一个明文单元损坏影响多个单元; 


    了解这些加密模式之后,再看openssl提供的接口就好理解了。

    下面接口来自“crypto/aes/aes.h”。有openssl源代码。
    //设置加密和解密器
    int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
    AES_KEY *key);
    int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
    AES_KEY *key);

    //默认的加密解密方式,參数好理解
    void AES_encrypt(const unsigned char *in, unsigned char *out,
    const AES_KEY *key);
    void AES_decrypt(const unsigned char *in, unsigned char *out,
    const AES_KEY *key);

    //以下这些也是经常使用的加密方式,可是參数非常多,而源代码对于參数使用介绍不多。仅仅能摸索
    void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
    const AES_KEY *key, const int enc);
    void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
    size_t length, const AES_KEY *key,
    unsigned char *ivec, const int enc); //參数相对复杂
    void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
    size_t length, const AES_KEY *key,
    unsigned char *ivec, int *num, const int enc);
    void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
    size_t length, const AES_KEY *key,
    unsigned char *ivec, int *num, const int enc);
    void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
    size_t length, const AES_KEY *key,
    unsigned char *ivec, int *num, const int enc);
    void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
    size_t length, const AES_KEY *key,
    unsigned char *ivec, int *num);
    void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
    size_t length, const AES_KEY *key,
    unsigned char ivec[AES_BLOCK_SIZE],
    unsigned char ecount_buf[AES_BLOCK_SIZE],
    unsigned int *num);

    从以下这个文件能够看出,AES_encrypt就是ecb加密的方式。而AES_set_encrypt_key和AES_encrypt,它们的实如今"crypto/aes/aes_x86core.c"和"crypto/aes/aes_core.c",也就是有两个版本号,依据平台选择。

    看源代码。

    调用实例:
    1. int aes_encrypt(char* in, char* key, char* out)//, int olen)  
    2. {  
    3.     if(!in || !key || !out) return 0;  
    4.     AES_KEY aes;  
    5.     if(AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)  
    6.     {  
    7.         return 0;  
    8.     }  
    9.     int len=strlen(in), en_len=0;  
    10.     while(en_len<len)//输入输出字符串够长。而且是AES_BLOCK_SIZE的整数倍,须要严格限制  
    11.     {  
    12.         AES_encrypt((unsigned char*)in, (unsigned char*)out, &aes);  
    13.         in+=AES_BLOCK_SIZE;  
    14.         out+=AES_BLOCK_SIZE;  
    15.         en_len+=AES_BLOCK_SIZE;  
    16.     }  
    17.     return 1;  
    18. }  
    19. int aes_decrypt(char* in, char* key, char* out)  
    20. {  
    21.     if(!in || !key || !out) return 0;  
    22.     AES_KEY aes;  
    23.     if(AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0)  
    24.     {  
    25.         return 0;  
    26.     }  
    27.     int len=strlen(in), en_len=0;  
    28.     while(en_len<len)  
    29.     {  
    30.         AES_decrypt((unsigned char*)in, (unsigned char*)out, &aes);  
    31.         in+=AES_BLOCK_SIZE;  
    32.         out+=AES_BLOCK_SIZE;  
    33.         en_len+=AES_BLOCK_SIZE;  
    34.     }  
    35.     return 1;  
    36. }  


    最后给出一个链接,利用openssl的AES接口进行编程。

    參考资料:

    分组对称加密模式:ECB/CBC/CFB/OFB缺CTR

    http://fossies.org/dox/openssl-1.0.1f/index.html (具体源代码)


    命令行下openssl对文件加密解密:

    --建立文件test.txt, 特意写入中英文

    # cd /tmp

    # echo "test測试" > test.txt

    --開始加密, 使用aes-128-cbc算法, 也能够使用其它算法, 通过查看openssl的帮助可获知

    # openssl aes-128-cbc -salt -in test.txt -out test.txt.aes
    enter aes-128-cbc encryption password:<输入密码>
    Verifying - enter aes-128-cbc encryption password:<确认密码>

    --查看加密前后的文件大小, 加密后文件明显增大了

    # ll test.txt*  
    -rw-r--r--  1 root root  9 Aug 11 15:42 test.txt
    -rw-r--r--  1 root root 32 Aug 11 15:43 test.txt.aes

    --查看加密前后的文件内容, 加密后文件无法直接查看, 显示乱码

    # cat test.txt
    test測试

    # cat test.txt.aes
    Salted__碾RTqm6棚顱

    --如今開始解密, 会提示输入password, 假设password有误则无法解密

    # openssl aes-128-cbc -d -salt -in test.txt.aes -out test.txt.out
    enter aes-128-cbc decryption password:<输入错误密码>
    bad decrypt
    6150:error:06065064:digital envelope routines:EVP_DecryptFinal:bad decrypt:evp_enc.c:438:

    # openssl aes-128-cbc -d -salt -in test.txt.aes -out test.txt.out
    enter aes-128-cbc decryption password:<输入正确密码>

    --查看解密前后的文件大小, 和加密前是一样的

    # ll test.txt*
    -rw-r--r--  1 root root  9 Aug 11 15:42 test.txt
    -rw-r--r--  1 root root 32 Aug 11 15:43 test.txt.aes
    -rw-r--r--  1 root root  9 Aug 11 15:45 test.txt.out

    --查看解密前后的文件内容, 和加密前是一样的

    # cat test.txt.out
    test測试

    这样的方法很适合Linux下的文件内容保密, 呵呵....以上命令加參数比較复杂, 我们能够把命令加參数做个函数, 然后放到.bash_profile里, 这样每次登陆后直接使用函数就可以, 例如以下:


    function jiami() 

     /usr/bin/openssl aes-128-cbc -salt -in $1 -out $1.aes && rm -f $1

    }

    function jiemi() 

     /usr/bin/openssl aes-128-cbc -d -salt -in $1.aes -out $1 && rm -f $1.aes

    }


    然后就能够例如以下使用了(注意输入參数都是原文件名称, 且会自己主动删除原文件):

    # jiami test.txt
    enter aes-128-cbc encryption password:
    Verifying - enter aes-128-cbc encryption password:

    # jiemi test.txt
    enter aes-128-cbc decryption password:

    # ll test.txt*  
    -rw-r--r--  1 root root 9 Aug 11 15:46 test.txt
    -rw-r--r--  1 root root 9 Aug 11 15:45 test.txt.out

    --End--
  • 相关阅读:
    [转]趣题:一个n位数平均有多少个单调区间?---- From Matrix67
    2015编程之美复赛
    Codeforces Round #304 (Div. 2)
    HDU 5226
    HDU 5225
    HDU 3666
    HDU 4598
    Codeforces Round #303 (Div. 2) E
    编程之美初赛第二场AB
    2015 编程之美初赛第一场 AC题
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/7250595.html
Copyright © 2020-2023  润新知