加密算法代码实践

实验目的

掌握各种对称算法接口的调用方法(C/C++方式)

掌握各种非对称算法接口的调用方法(C/C++方式)

掌握各种摘要算法接口的调用方法(C/C++方式)

实验原理

1.DES算法

des算法为密码体制中的对称密码体制,又被称为美国数据加密标准,是1972年美国IBM公司研制的对称密码体制加密算法。DES算法具有极高安全性,到目前为止,除了用穷举搜索法对DES算法进行攻击外,还没有发现更有效的办法。

2.AES运算

AES(The Advanced Encryption Standard)是美国国家标准与技术研究所用于加密电子数据的规范。它被预期能成为人们公认的加密包括金融、电信和政府数字信息的方法。该算法为比利时密码学家Joan Daemen和Vincent Rijmen所设计,结合两位作者的名字,以Rijndael之命名之,投稿高级加密标准的甄选流程。Rijdael的发音近于 "Rhinedoll,两位设计者的名字,参考荷兰语原发音可译为尤安•达蒙、文森特•莱蒙。(Joan不能译为女性化的名字"琼"。另外,西欧的姓名很多是有相同拉丁文或希腊文源头的,故译成中文是可能相同)

AES 是一个新的可以用于保护电子数据的加密算法。明确地说,AES 是一个迭代的、对称密钥分组的密码,它可以使用128、192 和 256 位密钥,并且用 128 位(16字节)分组加密和解密数据。与公共密钥密码使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换(permutations )和替换(substitutions)输入数据。

3.MD5原理概念

对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

在MD5算法中,首先需要对信息进行填充,使其位长对512求余的结果等于448。因此,信息的位长(Bits Length)将被扩展至N512+448,N为一个非负整数,N可以是零。填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后,在这个结果后面附加一个以64位二进制表示的填充前信息长度。经过这两步的处理,信息的位长=N512+448+64= (N+1)*512,即长度恰好是512的整数倍。这样做的原因是为满足后面处理中对信息长度的要求。表示第i个分组,每次的运算都由前一轮的128位结果值和第i块512bit值进行运算。初始的128位值为初试链接变量,这些参数用于第一轮的运算,以大端字节序来表示,他们分别为:A=0x01234567,B=0x89ABCDEF,C=0xFEDCBA98,D=0x76543210。

4.SHA-1算法

SHA (Secure Hash Algorithm,译作安全散列算法) 是美国国家安全局 (NSA) 设计,美国国家标准与技术研究院 (NIST) 发布的一系列密码散列函数。正式名称为 SHA 的家族第一个成员发布于 1993年。然而现在的人们给它取了一个非正式的名称 SHA-0 以避免与它的后继者混淆。两年之后, SHA-1,第一个 SHA 的后继者发布了。 另外还有四种变体,曾经发布以提升输出的范围和变更一些细微设计: SHA-224, SHA-256, SHA-384 和 SHA-512 (这些有时候也被称做 SHA-2)。

5.RSA算法

RSA公开密钥密码体制。所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。非常好用。

在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然秘密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK。正是基于这种理论,1978年出现了著名的RSA算法,它通常是先生成一对RSA 密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。

RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。RSA是被研究得最广泛的公钥算法,从提出到现在的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。

6.DSA算法原理

数字签名是数据在公开行信道中传输的安全保障,能够实现数据公开、公正、不可抵赖等特点的方法,只能公开的密钥、密码签名算法。国际公认的公开密钥签字算法主要有RSA算法、EIGAMAL算法或者其变形的签名算法。DSA(Digite Signature Arithmotic)是Schnore和ElGamal算法的变型。

美国国家标准局(NIST)1994年5月19日公布了数字签名标准的(DSS),标准采用的是算法便是DSA,密钥长度为512-1024位。密钥长度俞长,签名速度愈慢,制约运算速度的主要因素是大数的模指数预算。

使用vc6.0++进行调试 代码如下
cryptAlgorithm.h头文件内容:

#ifndef __CRYPT_ALGORITHM_H



#define __CRYPT_ALGORITHM_H



#define CRYPT_SUCCESS 0

#define CRYPT_VERIFY_ERROR 10000

typedef void* RSAKey;

typedef void* DSAKey;



int AES128_ECB_encrypt(unsigned char *key,

                    unsigned char *input,

                    int inputLen,

                    unsigned char *output,

                    int *outputLen);



int AES128_ECB_decrypt(unsigned char *key,

                    unsigned char *input,

                    int inputLen,

                    unsigned char *output,

                    int *outputLen);



int AES128_CBC_encrypt(unsigned char *key,

                    unsigned char *iv,

                    unsigned char *input,

                    int inputLen,

                    unsigned char *output,

                    int *outputLen);



int AES128_CBC_decrypt(unsigned char *key,

                    unsigned char *iv,

                    unsigned char *input,

                    int inputLen,

                    unsigned char *output,

                    int *outputLen);



int DES_ECB_encrypt(unsigned char *key,

                    unsigned char *input,

                    int inputLen,

                    unsigned char *output,

                    int *outputLen);



int DES_ECB_decrypt(unsigned char *key,

                    unsigned char *input,

                    int inputLen,

                    unsigned char *output,

                    int *outputLen);



int DES_CBC_encrypt(unsigned char *key,

                    unsigned char *iv,

                    unsigned char *input,

                    int inputLen,

                    unsigned char *output,

                    int *outputLen);



int DES_CBC_decrypt(unsigned char *key,

                    unsigned char *iv,

                    unsigned char *input,

                    int inputLen,

                    unsigned char *output,

                    int *outputLen);



int MD5(unsigned char *input,

        int inputLen,

        unsigned char *output,

        int *outputLen);



int SHA1(unsigned char *input,

        int inputLen,

        unsigned char *output,

        int *outputLen);



int RSA1024_generateKey(RSAKey *key);



int RSA1024_freeKey(RSAKey *key);



int RSA1024_privateKeyEnc(RSAKey key,

                    unsigned char *input,

                    int inputLen,

                    unsigned char *output,

                    int *outputLen);



int RSA1024_privateKeyDec(RSAKey key,

                    unsigned char *input,

                    int inputLen,

                    unsigned char *output,

                    int *outputLen);



int RSA1024_publicKeyEnc(RSAKey key,

                    unsigned char *input,

                    int inputLen,

                    unsigned char *output,

                    int *outputLen);



int RSA1024_publicKeyDec(RSAKey key,

                    unsigned char *input,

                    int inputLen,

                    unsigned char *output,

                    int *outputLen);



int DSA_generateKey(DSAKey *key);



int DSA_freeKey(DSAKey key);



int DSA_dosign(DSAKey key,

                unsigned char *dgst,

                int dgstLen,

                unsigned char *sig,

                int *sigLen);



int DSA_doverify(DSAKey key,

                unsigned char *dgst,

                int dgstLen,

                unsigned char *sig,

                int sigLen);



#endif

test.cpp文件内容:

#include <stdio.h>

#include "cryptAlgorithm.h"



static void hex_dump( const char *desc, unsigned char *data, int data_cb )

{

    int i = 0;

    

    if( desc ) {

        printf( "%s, size=%d
", desc, data_cb );

    }

    else {

        printf( "size=%d
", data_cb );

    }



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

        if( i>0 && i%32 == 0 )

            printf( "
" );



        printf( "%02X ", data[i] );

    }



    printf( "
" );

}



void test_AES128_ECB()

{

    unsigned char key[16] = { 0 };

    unsigned char input[1008] = { 0 };

    unsigned char output[1008] = { 0 };

    int i;

    int ret;

    int len;



    //初始化密钥

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

        key[i] = i;

    }

    //初始化明文输入

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

        input[i] = i;

    }



    //加密

    ret = AES128_ECB_encrypt(key, input, 1000, output, &len);

    printf("AES128_ECB_encrypt return %d
", ret);

    hex_dump("AES128_ECB_encrypt results", output, len);



    //解密

    ret = AES128_ECB_decrypt(key, output, len, input, &len);

    printf("AES128_ECB_decrypt return %d
", ret);

    hex_dump("AES128_ECB_decrypt results", input, len);

}



void test_AES128_CBC()

{

    unsigned char key[16] = { 0 };

    unsigned char iv[16] = { 0 };

    unsigned char input[1008] = { 0 };

    unsigned char output[1008] = { 0 };

    int i;

    int ret;

    int len;



    //初始化密钥

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

        key[i] = i;

    }

    //初始化IV向量,CBC模式必须要有IV

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

        iv[i] = i+100;

    }

    //初始化明文输入

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

        input[i] = i;

    }



    //加密

    ret = AES128_CBC_encrypt(key, iv, input, 1000, output, &len);

    printf("AES128_CBC_encrypt return %d
", ret);

    hex_dump("AES128_CBC_encrypt results", output, len);



    //解密

    ret = AES128_CBC_decrypt(key, iv, output, len, input, &len);

    printf("AES128_CBC_decrypt return %d
", ret);

    hex_dump("AES128_CBC_decrypt results", input, len);

}



void test_DES_ECB()

{

    unsigned char key[8] = { 0 };

    unsigned char input[1008] = { 0 };

    unsigned char output[1008] = { 0 };

    int i;

    int ret;

    int len;



    //初始化密钥

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

        key[i] = i;

    }

    //初始化明文输入

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

        input[i] = i;

    }



    //加密

    ret = DES_ECB_encrypt(key, input, 1003, output, &len);

    printf("DES_ECB_encrypt return %d
", ret);

    hex_dump("DES_ECB_encrypt results", output, len);



    //解密

    ret = DES_ECB_decrypt(key, output, len, input, &len);

    printf("DES_ECB_decrypt return %d
", ret);

    hex_dump("DES_ECB_decrypt results", input, len);

}



void test_DES_CBC()

{

    unsigned char key[8] = { 0 };

    unsigned char iv[8] = { 0 };

    unsigned char input[1008] = { 0 };

    unsigned char output[1008] = { 0 };

    int i;

    int ret;

    int len;



    //初始化密钥

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

        key[i] = i;

    }

    //初始化IV向量,CBC加密模式必须要有IV向量

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

        iv[i] = i+100;

    }

    //初始化明文输入

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

        input[i] = i;

    }



    //加密

    //输入1003字节,加密时会自动做8字节补齐,输出应该是1008字节

    //补齐时按照分组长度对齐,DES的分组长度是8字节

    ret = DES_CBC_encrypt(key, iv, input, 1003, output, &len);

    printf("DES_CBC_encrypt return %d
", ret);

    hex_dump("DES_CBC_encrypt results", output, len);



    //解密

    ret = DES_CBC_decrypt(key, iv, output, len, input, &len);

    printf("DES_CBC_decrypt return %d
", ret);

    hex_dump("DES_CBC_decrypt results", input, len);

}



void test_MD5()

{

    unsigned char input[1000] = { 0 };

    unsigned char dgst[16] = { 0 };    //md5输出是16字节

    int i;

    int ret;

    int len;



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

        input[i] = i;

    }



    //计算md5摘要

    ret = MD5(input, 1000, dgst, &len);

    printf("MD5 return %d
", ret);

    hex_dump("MD5 results", dgst, len);

}



void test_SHA1()

{

    unsigned char input[1000] = { 0 };

    unsigned char dgst[20] = { 0 };    //sha1输出是20字节

    int i;

    int ret;

    int len;



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

        input[i] = i;

    }



    //计算sha1摘要

    ret = SHA1(input, 1000, dgst, &len);

    printf("SHA1 return %d
", ret);

    hex_dump("SHA1 results", dgst, len);

}



void test_RSA1024()

{

    RSAKey key;

    unsigned char input[128] = { 0 };

    unsigned char output[128] = { 0 };

    int i;

    int ret;

    int len;



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

        input[i] = i;

    }



    //生成RSA密钥对

    RSA1024_generateKey(&key);



    //私钥加密,输入必须小于密钥长度,即128字节

    ret = RSA1024_privateKeyEnc(key, input, 100, output, &len);

    printf("RSA1024_privateKeyEnc return %d
", ret);

    hex_dump("RSA1024_privateKeyEnc results", output, len);



    //公钥解密

    ret = RSA1024_publicKeyDec(key, output, len, input, &len);

    printf("RSA1024_publicKeyDec return %d
", ret);

    hex_dump("RSA1024_publicKeyDec results", input, len);



    //公钥加密,输入必须小于密钥长度,即128字节

    ret = RSA1024_publicKeyEnc(key, input, 100, output, &len);

    printf("RSA1024_publicKeyEnc return %d
", ret);

    hex_dump("RSA1024_publicKeyEnc results", output, len);



    //私钥解密

    ret = RSA1024_privateKeyDec(key, output, len, input, &len);

    printf("RSA1024_privateKeyDec return %d
", ret);

    hex_dump("RSA1024_privateKeyDec results", input, len);



    RSA1024_freeKey(key);

}



void test_DSA()

{

    DSAKey key;

    unsigned char input[1000] = { 0 };

    unsigned char dgst[20] = { 0 };

    unsigned char output[128] = { 0 };

    int i;

    int ret;

    int dgstLen;

    int sigLen;



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

        input[i] = i;

    }



    //签名时先做摘要

    ret = SHA1(input, 1000, dgst, &dgstLen);

    printf("SHA1 return %d
", ret);

    hex_dump("SHA1 results", dgst, dgstLen);



    //生成DSA密钥对

    DSA_generateKey(&key);



    //DSA签名

    ret = DSA_dosign(key, dgst, dgstLen, output, &sigLen);

    printf("DSA_dosign return %d
", ret);

    hex_dump("DSA_dosign results", output, sigLen);



    //修改签名值,再去验证签名,肯定会验证失败

//    output[10] = 1;



    //DSA验签

    ret = DSA_doverify(key, dgst, dgstLen, output, sigLen);

    printf("DSA_doverify return %d
", ret);

    if( ret == CRYPT_SUCCESS ) {

        printf("verify OK
");

    }

    else {

        printf("verify FAIL
");

    }



    DSA_freeKey(key);

}





void main()

{

//    test_AES128_ECB();

//    test_AES128_CBC();

//    test_DES_ECB();

//    test_DES_CBC();

//    test_MD5();

//    test_SHA1();

//    test_RSA1024();

    test_DSA();

}

运行结果如下 测出ECB,MD5,SHA1(),DSA等加密算法的长度和相关加密实现过程:

Snipaste_2018-04-05_13-26-16.jpg

加密解密真j儿难。。。。都是Algorithm

继续刷网技视频去了。。爱好只能是爱好而已。。。

原文地址:https://www.cnblogs.com/whatiwhere/p/8722239.html