加载中…
个人资料
elecs
elecs
  • 博客等级:
  • 博客积分:0
  • 博客访问:53,097
  • 关注人气:1
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
正文 字体大小:

使用Openssl DES API

(2018-10-16 17:41:06)
标签:

openssl

des

分类: 信息安全

现在OpenSSL达到了1.0.0版本,下面我们看看OpenSSL中包含的各种DES API如何用于加密和解密数据的,由于互联网上还缺乏如何实际使用OpenSSL DES的例子,下面在本文包含一些示例。

 

DES为分组密码算法,在分组密码中,来自明文的N比特块被来自密文的N比特块替换。理想情况下,输入块和输出块之间的关系是完全随机但可逆的。

 

FIPS 81标准规定了许多操作模式。这些模式指定了如何加密和解密数据。总结如下。

电子密码本模式(ECB

密码块链接模式(CBC

密码反馈模式(CFB

输出反馈模式(OFB

三重DES ECB模式

三重DES CBC模式

 

一、环境准备

安装openssl开发包

apt-get install libssl-dev

二、示例

1example1显示如何使用DES_ecb_encrypt()使用ecb模式来加密或解密。如果encrypt参数是DES_ENCRYPT则使用指定的key_schedule加密;如果encrypt参数是DES_DECRYPT则解密。

#include

#include

#include

#include

#include

 

#define BUFSIZE 64

 

int main(void)

{

    unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE];

    unsigned char *e = out;

 

    DES_cblock key;

    DES_cblock seed = {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10};

    DES_key_schedule keysched;

 

    memset(in, 0, sizeof(in));

    memset(out, 0, sizeof(out));

    memset(back, 0, sizeof(back));

 

    RAND_seed(seed, sizeof(DES_cblock));

 

    DES_random_key(&key);

 

    DES_set_key((DES_cblock *)key, &keysched);

 

   

    strcpy(in, "HillTown");

 

    printf("Plaintext: [%s]\n", in);

 

    DES_ecb_encrypt((DES_cblock *)in,(DES_cblock *)out, &keysched, DES_ENCRYPT);

 

    printf("Ciphertext:");

    while (*e) printf(" [x]", *e++);

    printf("\n");

 

    DES_ecb_encrypt((DES_cblock *)out,(DES_cblock *)back, &keysched, DES_DECRYPT);

 

    printf("Decrypted Text: [%s]\n", back);

 

    return(0);

}

编译运行

gcc -o example1 example1.c –lcrypto

使用Openssl DES API

 

2example2演示Triple-DES模式。FIPS-46Triple-DES指定了两种模式

Ø  EDE(加密 - 解密 - 加密),其中 密文 = Ek3Dk2Ek1(明文)))

Ø  EEE(加密 - 加密 - 加密),其中 密文 = Ek3Ek2Ek1(明文)))

此外,ANSI X9.52Triple-DES定义了三个关键选项

Ø  k1= k2= k3

Ø  k1= k2k1 = k3k2= k3

Ø  k1 = k2 = k3

对于Triple-DES,建议的使用模式(根据FIPS-46)是EEEEDE,具有三个独立生成的密钥,即总共168个密钥位。OpenSSL使用EDE模式。

#include

#include

#include

#include

#include

 

#define BUFSIZE 1024

 

int main(void)

{

    unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE];

    unsigned char *e = out;

    int i;

 

    DES_cblock key1, key2, key3;

    DES_cblock seed = {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10};

    DES_key_schedule ks1, ks2, ks3;

 

    memset(in, 0, sizeof(in));

    memset(out, 0, sizeof(out));

    memset(back, 0, sizeof(back));

 

    RAND_seed(seed, sizeof(DES_cblock));

 

    DES_random_key(&key1);

    DES_random_key(&key2);

    DES_random_key(&key3);

 

    DES_set_key((DES_cblock *)key1, &ks1);

    DES_set_key((DES_cblock *)key2, &ks2);

    DES_set_key((DES_cblock *)key3, &ks3);

 

   

    strcpy(in, "Now is the time for all men to stand up and be counted");

 

    printf("Plaintext: [%s]\n", in);

 

    for (i = 0; i < 63; i += 8) {

        DES_ecb3_encrypt((DES_cblock *)(in + i),(DES_cblock *)(out + i), &ks1, &ks2, &ks3, DES_ENCRYPT);

    }

 

    printf("Ciphertext:");

    while (e++) printf(" [x]", *e++);

    printf("\n");

 

    for (i = 0; i < 63; i += 8) {

        DES_ecb3_encrypt((DES_cblock *)(out + i),(DES_cblock *)(back + i), &ks1, &ks2, &ks3, DES_DECRYPT);

    }

 

    printf("Decrypted Text: [%s]\n", back);

 

    exit(0);

}

如您所见,此示例使用三个不同的键(k1= k2= k3

 

3example3演示cbc模式,在此模式下,每个块与加密前的前一个密码块进行异或。

对于第一个块,我们从初始化向量(ivec)开始。

请注意,在libcrypto中有DES_cbc_encrypt()和DES_ncbc_encrypt()。我建议你只使用ncbc版本(n代表新版本)。

#include

#include

#include

#include

#include

 

#define BUFSIZE 512

 

int main(void)

{

    unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE];

    unsigned char *e = out;

    int len;

 

    DES_cblock key;

    DES_cblock seed = {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10};

    DES_cblock ivsetup = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8};

    DES_key_schedule keysched;

    DES_cblock ivec;

 

    memset(in, 0, sizeof(in));

    memset(out, 0, sizeof(out));

    memset(back, 0, sizeof(back));

 

    RAND_seed(seed, sizeof(DES_cblock));

 

    DES_random_key(&key);

    DES_set_odd_parity(&key);

    if (DES_set_key_checked((DES_cblock *)key, &keysched))

    {

        fprintf(stderr, "ERROR: Unable to set key schedule\n");

        exit(1);

    }

 

   

    strcpy(in, "Now is the time for all men to stand up and be counted");

 

    printf("Plaintext: [%s]\n", in);

 

    len = strlen(in);

    memcpy(ivec, ivsetup, sizeof(ivsetup));

    DES_ncbc_encrypt(in, out, len, &keysched, &ivec, DES_ENCRYPT);

 

    printf("Ciphertext:");

    while (*e) printf(" [x]", *e++);

    printf("\n");

 

    memcpy(ivec, ivsetup, sizeof(ivsetup));

    DES_ncbc_encrypt(out, back, len, &keysched, &ivec, DES_DECRYPT);

 

    printf("Decrypted Text: [%s]\n", back);

 

    exit(0);

}

请注意,我在解密密文之前重新初始化ivec。如果您不重新初始化ivec,您的解密文本将不正确。

 

4example4使用DES_ede3_ncbc_encrypt()来实现具有三个密钥的外部三重CBC DES加密。这意味着CBC模式内的每个DES操作是C = Eks3Dks2Eks1M)))。这是SSL使用的模式。

#include

#include

#include

#include

#include

 

#define BUFSIZE 512

 

int main(void)

{

    unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE];

    unsigned char *e = out;

    int len;

 

    DES_cblock key1, key2, key3;

    DES_cblock seed = {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10};

    DES_cblock ivsetup = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8};

    DES_cblock ivec;

    DES_key_schedule ks1, ks2, ks3;

 

    memset(in, 0, sizeof(in));

    memset(out, 0, sizeof(out));

    memset(back, 0, sizeof(back));

 

    RAND_seed(seed, sizeof(DES_cblock));

 

    DES_random_key(&key1);

    DES_random_key(&key2);

    DES_random_key(&key3);

 

    DES_set_key((DES_cblock *)key1, &ks1);

    DES_set_key((DES_cblock *)key2, &ks2);

    DES_set_key((DES_cblock *)key3, &ks3);

 

   

    strcpy(in, "Now is the time for all men to stand up and be counted");

 

    printf("Plaintext: [%s]\n", in);

 

    len = strlen(in);

    memcpy(ivec, ivsetup, sizeof(ivsetup));

    DES_ede3_cbc_encrypt(in, out, len, &ks1, &ks2, &ks3, &ivec, DES_ENCRYPT);

 

    printf("Ciphertext:");

    while (*e) printf(" [x]", *e++);

    printf("\n");

 

    len = strlen(out);

    memcpy(ivec, ivsetup, sizeof(ivsetup));

    DES_ede3_cbc_encrypt(out, back, len, &ks1, &ks2, &ks3, &ivec, DES_DECRYPT);

 

    printf("Decrypted Text: [%s]\n", back);

 

    exit(0);

}

请注意在解密密文之前需要重新初始化ivec。如果不这样做,结果明文的前64位将是不正确的。

 

5example5显示了密码反馈(CFB)模式的使用。CFBCBC的近亲,但如果选择1位模式,则它是自同步流密码。

#include

#include

#include

#include

#include

 

#define BUFSIZE 256

#define CFBMODE 1

 

int main(void)

{

    unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE];

    unsigned char *e = out;

    int len;

 

    DES_cblock key;

    DES_cblock seed = {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10};

    DES_cblock ivecstr = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8};

    DES_cblock ivec;

    DES_key_schedule ks;

 

    memset(in, 0, sizeof(in));

    memset(out, 0, sizeof(out));

    memset(back, 0, sizeof(back));

 

    RAND_seed(seed, sizeof(DES_cblock));

 

    DES_random_key(&key);

    DES_set_key((DES_cblock *)key, &ks);

 

   

    strcpy(in, "Philippines");

 

    printf("Plaintext: [%s]\n", in);

 

    memcpy(ivec, ivecstr, sizeof(ivecstr));

    len = strlen(in);

 

    DES_cfb_encrypt(in, out, CFBMODE, len, &ks, &ivec, DES_ENCRYPT);

 

    printf("Ciphertext:");

    while (*e) printf(" [x]", *e++);

    printf("\n");

 

    len = strlen(out);

    memcpy(ivec, ivecstr, sizeof(ivecstr));

 

    DES_cfb_encrypt(out, back, CFBMODE, len, &ks, &ivec, DES_DECRYPT);

 

    printf("Decrypted Text: [%s]\n", back);

 

    exit(0);

}

 

6example6使用CBF64模式的示例,也是第一次使用ASCII字符串作为初始化向量和DES密钥。

#include

#include

#include

#include

 

#define BUFSIZE 256

 

int main(void)

{

    unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE];

    unsigned char *e = out;

    int len;

    int n = 0;

 

    static char *keystr = "0123456789abcdef";

    static char *ivecstr = "0123456789abcdef";

 

    DES_cblock ivec;

    DES_key_schedule ks;

 

    memset(in, 0, sizeof(in));

    memset(out, 0, sizeof(out));

    memset(back, 0, sizeof(back));

 

    strcpy(in,"Now is the time for all.");

    DES_set_key((DES_cblock *)keystr, &ks);

 

    printf("Plaintext: [%s]\n", in);

 

    memcpy(ivec, (DES_cblock *)ivecstr, sizeof(ivec));

    len = strlen(in) + 1;

 

    DES_cfb64_encrypt(in, out, len, &ks, &ivec, &n, DES_ENCRYPT);

 

    printf("Ciphertext:");

    while (*e) printf(" [x]", *e++);

    printf("\n");

 

    memcpy(ivec, (DES_cblock *)ivecstr, sizeof(ivec));

 

    DES_cfb64_encrypt(out, back, len, &ks, &ivec, &n, DES_DECRYPT);

 

    printf("Decrypted Text: [%s]\n", back);

 

    exit(0);

}

 

7example7演示了使用8OFB模式。该模式是附加流密码,其中密文中的错误不会被扩展以在解密的明文中引起额外的错误。因此,密文中的单个误码位导致解密的明文中只有一个比特出错。根据OpenSSL手册页,此模式仅应用于小尺寸的明文。通过试验numbitsDES手册页的BUGS部分,我建议你总是使用值8来表示numbits

#include

#include

#include

#include

#include

 

#define BUFSIZE 256

 

int main(void)

{

    unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE];

    unsigned char *e = out;

    char *keystr = "Philippines06235";

    int len, n, result;

 

    DES_cblock key;

    DES_cblock ivecstr = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8};

    DES_cblock ivec;

    DES_key_schedule ks;

 

    memset(in, 0, sizeof(in));

    memset(out, 0, sizeof(out));

    memset(back, 0, sizeof(back));

 

    DES_string_to_key(keystr, &key);

 

    if ((result = DES_set_key_checked((DES_cblock *)key, &ks)) != 0) {

        if (result == -1) {

            printf("ERROR: key parity is incorrect\n");

        } else {

            printf("ERROR: weak or semi-weak key\n");

        }

        exit(1);

    }

 

    strcpy(in,"The Chocolate Hills of Bohol are wonderful.");

 

    printf("Plaintext: [%s]\n", in);

 

    memcpy(ivec, ivecstr, sizeof(ivecstr));

    len = strlen(in);

    printf("Plaintext Length: %d\n", len);

 

    DES_ofb_encrypt(in, out, 8, len, &ks, &ivec);

 

    n = 0;

    printf("Ciphertext:");

    while (*e) {

        printf(" [x]", *e++);

        n++;

    }

    printf("\n");

    printf("Ciphertext Length: %d\n", n);

 

    len = strlen(out);

    memcpy(ivec, ivecstr, sizeof(ivecstr));

 

    DES_ofb_encrypt(out, back, 8, len, &ks, &ivec);

 

    printf("Decrypted Text: [%s]\n", back);

 

    exit(0);

}

请注意使用DES_string_to_key()将字符串转换为密钥。输入的字符串长度至少应为16个字符。DES_string_to_key()设置奇数奇偶校验,因此不需要调用DES_set_odd_parity()。

 

8example8示例使用ede3_ofb64_encrypt()来执行加密和解密。它还从外部文件中读取明文。为了简化和简化示例,我设置k1 = k2 = k3。我将由您修改示例以支持k1= k2= k3的情况。

#include

#include

#include

#include

 

#define BUFSIZE 1024

 

int main(int argc, char *argv[])

{

    unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE];

    char buf[201];

    char *keystr = "Victoria Harbour";

    unsigned char *e = out;

    FILE *fin;

    int i, num, len, result;

    int n = 0;

 

    DES_cblock key;

    DES_cblock ivsetup = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8};

    DES_key_schedule ks;

    DES_cblock ivec;

 

    if (argc != 2) {

        printf("ERROR: plaintext filename required\n");

        exit(1);

    }

 

    memset(in, 0, sizeof(in));

    memset(out, 0, sizeof(out));

    memset(back, 0, sizeof(back));

 

    DES_string_to_key(keystr, &key);

 

    if ((result = DES_set_key_checked((DES_cblock *)key, &ks)) != 0) {

        if (result == -1) {

            printf("ERROR: key parity is incorrect\n");

        } else {

            printf("ERROR: weak or semi-weak key\n");

        }

        exit(1);

    }

 

    fin = fopen(argv[1], "r");

    if (!fin) {

        printf(" ERROR: opening input file\n");

        exit(1);

    }

    while(fgets(buf, 200, fin) != NULL) {

        strcat(in, buf);

    }

    fclose(fin);

 

    printf("Plaintext: [%s]\n", in);

    len = strlen(in);

    printf("Plaintext Length: %d\n", len);

 

    memcpy(ivec, ivsetup, sizeof(ivsetup));

    num = 0;

    for (i = 0; i < len; i++) {

        DES_ede3_ofb64_encrypt(&(in[i]), &(out[i]), 1, &ks, &ks, &ks, &ivec, &num);

    }

 

    n = 0;

    printf("Ciphertext:");

    while (*e) {

        printf(" [x]", *e++);

        n++;

    }

    printf("\n");

    printf("Ciphertext Length: %d\n", n);

 

    memcpy(ivec, ivsetup, sizeof(ivsetup));

    num = 0;

    for (i = 0; i < len; i++) {

        DES_ede3_ofb64_encrypt(&(out[i]), &(back[i]), 1, &ks, &ks, &ks, &ivec, &num);

    }

 

    printf("Decrypted Text: [%s]\n", back);

 

    exit(0);

}

下面为示例输出

使用Openssl DES API

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有