zoukankan      html  css  js  c++  java
  • 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--
  • 相关阅读:
    HTML DOM 12 表格排序
    HTML DOM 10 常用场景
    HTML DOM 10 插入节点
    HTML DOM 09 替换节点
    HTML DOM 08 删除节点
    HTML DOM 07 创建节点
    022 注释
    024 数字类型
    005 基于面向对象设计一个简单的游戏
    021 花式赋值
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/7250595.html
Copyright © 2011-2022 走看看