加解密 C语言实现
阅读原文时间:2023年07月11日阅读:2

1.加密的基本原理

加密分为对称加密和非对称加密,对称加密就是加密方和解密放用同一个密钥。

加密是分组加密,即将明文数据分成多个密钥大小的块,依次和密钥运算,输出密文。

padding,由于加密需要分组,就要保证最后一组数据大小和密钥一样大,补齐方式有多种,常见的是缺几补几。

推荐博客:

https://www.cnblogs.com/adylee/archive/2007/09/14/893438.html

2.常用库

openssl 下 aes.h

/* crypto/aes/aes.h */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
*/

#ifndef HEADER_AES_H

define HEADER_AES_H

include

ifdef OPENSSL_NO_AES

error AES is disabled.

endif

include

define AES_ENCRYPT 1

define AES_DECRYPT 0

/*
* Because array size can't be a const in C, the following two are macros.
* Both sizes are in bytes.
*/

define AES_MAXNR 14

define AES_BLOCK_SIZE 16

#ifdef __cplusplus
extern "C" {
#endif

/* This should be a hidden type, but EVP requires that the size be known */
struct aes_key_st {

ifdef AES_LONG

unsigned long rd\_key\[4 \* (AES\_MAXNR + 1)\];  

else

unsigned int rd\_key\[4 \* (AES\_MAXNR + 1)\];  

endif

int rounds;  

};
typedef struct aes_key_st AES_KEY;

const char *AES_options(void);

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);

int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int private_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);
/* NB: the IV is _two_ blocks long */
void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc);
/* NB: the IV is _four_ blocks long */
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);

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

#ifdef __cplusplus
}
#endif

#endif /* !HEADER_AES_H */

3.使用

(1)下面以 aes-128-ecb 并使用base64的实现,aes表示对称加密,ceb是一种加密模式,128表示128bit即16Bytes的密钥长度,base64是一种编码方式,将不可见字符转为可见字符,详见百度百科。

#ifndef _AES_128_ECB_H_
#define _AES_128_ECB_H_

int base64_encode(char *in_str, int in_len, char *out_str);
int base64_decode(char *in_str, int in_len, char *out_str);
int aes_128_ecb_encode(char *in, int in_len, char *out, int *out_len, const unsigned char *key);
int aes_128_ecb_decode(char *in, int in_len, char *out, int *out_len, const unsigned char *key);

#endif

#include
#include
#include
#include
#include
#include
#include
#include "openssl/pem.h"
#include "openssl/bio.h"
#include "openssl/evp.h"
#include "openssl/aes.h"
#include
#include

#define BUF_SIZE 1024

int base64_encode(char *in_str, int in_len, char *out_str);
int base64_decode(char *in_str, int in_len, char *out_str);
int aes_128_ecb_encode(char *in, int in_len, char *out, int *out_len, const unsigned char *key);
int aes_128_ecb_decode(char *in, int in_len, char *out, int *out_len, const unsigned char *key);

int main()
{
//AES_KEY aes;
struct aes_key_st enc_aes, dec_aes;
const unsigned char *in, *key = (unsigned char *)"f29848221a51a2bb";
unsigned char *out, buf2[BUF_SIZE] = {0};
int i, len, out_len;
int pading_begin, pading_end, pading;

struct stat st;  
int fd;  
char \*buf;  
stat("./tmp", &st);  
printf("size : %d\\n", st.st\_size);  
buf= (char \*)malloc(st.st\_size\*2);  
fd = open("./tmp", O\_RDONLY);  
int nbytes = read(fd, buf, st.st\_size);  
printf("buf : \\n%s\\n", buf);  
//printf("nbytes : %d\\n", nbytes);  
//printf("st\_size : %d\\n", st.st\_size);

// strncpy((char *)buf, "192.168.3.10", 1024);
// out_len = sizeof(buf);
out_len = st.st_size;
int len2 = strlen(buf);
//aes_128_ecb_encode(buf, strlen(buf), buf, &out_len, key);
// out_len = base64_encode(buf, out_len, buf);
// printf("base64_encode : \n%s\n", buf);
out_len = base64_decode(buf, out_len, buf);
aes_128_ecb_decode(buf, out_len, buf, &out_len, key);
printf("decode : \n%s\n", buf);

printf("len = %d\\n", st.st\_size);  
printf("len2 = %d\\n", len2);  

#if 0
printf("%s\n", AES_options());
if (AES_set_encrypt_key(key, 128, &enc_aes) < 0) {
printf("failed to set enc key");
exit(-1);
}
strncpy((char *)buf, "192.168.3.10", 1024);
in = buf;
out = buf;
printf("before encrypt : \n%s\n", buf);
/*-----------------------------pading begin-----------------------------*/
len = strlen((const char *)buf);
i = len/AES_BLOCK_SIZE + 1;
pading_end = i*AES_BLOCK_SIZE;
pading_begin = len;
printf("len = %d\n, i*AES_BLOCK_SIZE = %d\n", len, (i+1)*AES_BLOCK_SIZE);
pading = pading_end - pading_begin;
printf("pading : %d\n", pading);
memset((void *)(in + pading_begin), pading, pading);
len = i*AES_BLOCK_SIZE;
/*-----------------------------pading end-----------------------------*/
printf("after pading : \n%s\n", buf);

/\*-----------------------------encode begin-----------------------------\*/  
for (i = 0; (i+1)\*AES\_BLOCK\_SIZE <= len; i++) {  
    AES\_ecb\_encrypt(in+i\*AES\_BLOCK\_SIZE, out+i\*AES\_BLOCK\_SIZE, &enc\_aes, AES\_ENCRYPT);  
}  
/\*-----------------------------encode end-----------------------------\*/  
printf("after encrypt : \\n%s\\n", buf);  
/\*-----------------------------base64 encode begin-----------------------------\*/  
base64\_encode(buf, len, buf);  
printf("after base64 encode : \\n%s\\n", buf);  
/\*-----------------------------base64 encode end-----------------------------\*/  
/\*-----------------------------base64 decode begin-----------------------------\*/  
base64\_decode(buf, strlen(buf), buf);  
printf("after base64 decode : \\n%s\\n", buf);  
/\*-----------------------------base64 decode end-----------------------------\*/  
if (AES\_set\_decrypt\_key(key, 128, &dec\_aes) < 0) {  
    printf("failed to set dec key");  
    exit(-1);  
}  
printf("before decrypt : \\n%s\\n", buf);  
for (i = 0; (i+1)\*AES\_BLOCK\_SIZE <= len; i++) {  
    AES\_ecb\_encrypt(in+i\*AES\_BLOCK\_SIZE, out+i\*AES\_BLOCK\_SIZE, &dec\_aes, AES\_DECRYPT);  
}  
pading = in\[len-1\];  
\*(char \*)(in + len - pading) = '\\0';

printf("after decrypt : \\n%s\\n", buf);  

#endif

return 0;  

}

int base64_encode(char *in_str, int in_len, char *out_str)
{
BIO *b64, *bio;
BUF_MEM *bptr = NULL;
size_t size = 0;

if (in\_str == NULL || out\_str == NULL)  
    return -1;

b64 = BIO\_new(BIO\_f\_base64());  
bio = BIO\_new(BIO\_s\_mem());  
bio = BIO\_push(b64, bio);  
BIO\_write(bio, in\_str, in\_len);  
BIO\_flush(bio);  
BIO\_get\_mem\_ptr(bio, &bptr);  
memcpy(out\_str, bptr->data, bptr->length);  
out\_str\[bptr->length\] = '\\0';  
size = bptr->length;  
BIO\_free\_all(bio);

return size;  

}

int base64_decode(char *in_str, int in_len, char *out_str)
{
BIO *b64, *bio;
BUF_MEM *bptr = NULL;
int counts;
int size = 0;

if (in\_str == NULL || out\_str == NULL)  
    return -1;  
b64 = BIO\_new(BIO\_f\_base64());  
BIO\_set\_flags(b64, BIO\_FLAGS\_BASE64\_NO\_NL);  
bio = BIO\_new\_mem\_buf(in\_str, in\_len);  
bio = BIO\_push(b64, bio);  
size = BIO\_read(bio, out\_str, in\_len);  
out\_str\[size\] = '\\0';  
BIO\_free\_all(bio);

return size;  

}
int aes_128_ecb_encode(char *in, int in_len, char *out, int *out_len, const unsigned char *key)
{
/*-----------------------------pading begin-----------------------------*/
int i, pading_end, pading_begin, ret = 0, pading;
struct aes_key_st enc_aes;
if (in_len > *out_len) {
printf("aes_128_ecb_encode err : in_len > out_len\n");
ret = -1;
goto __end__;
}
if (AES_set_encrypt_key(key, 128, &enc_aes) < 0) {
printf("failed to set enc key");
ret = -1;
goto __end__;
}
memcpy(out, in, in_len);
i = in_len/AES_BLOCK_SIZE + 1;
pading_end = i*AES_BLOCK_SIZE;
pading_begin = in_len;
pading = pading_end - pading_begin;
memset((void *)(out + pading_begin), pading, pading);
*out_len = i*AES_BLOCK_SIZE;
/*-----------------------------pading end-----------------------------*/
/*-----------------------------encode begin-----------------------------*/
for (i = 0; (i+1)*AES_BLOCK_SIZE <= *out_len; i++) {
AES_ecb_encrypt(out+i*AES_BLOCK_SIZE, out+i*AES_BLOCK_SIZE, &enc_aes, AES_ENCRYPT);
}
/*-----------------------------encode end-----------------------------*/

__end__:

return ret;  

}

int aes_128_ecb_decode(char *in, int in_len, char *out, int *out_len, const unsigned char *key)
{
int i = 0, pading, ret = 0;
struct aes_key_st dec_aes;

if (in\_len == 0) {  
    goto \_\_end\_\_;  
}  
if (in\_len > \*out\_len) {  
    printf("aes\_128\_ecb\_decode err : in\_len > out\_len\\n");  
    ret = -1;  
    goto \_\_end\_\_;  
}  
if (AES\_set\_decrypt\_key(key, 128, &dec\_aes) < 0) {  
    printf("failed to set dec key");  
    ret = -1;  
    goto \_\_end\_\_;  
}  
memcpy(out, in, in\_len);  
\*out\_len = in\_len;  
for (i = 0; (i+1)\*AES\_BLOCK\_SIZE <= \*out\_len; i++) {  
    AES\_ecb\_encrypt(out+i\*AES\_BLOCK\_SIZE, out+i\*AES\_BLOCK\_SIZE, &dec\_aes, AES\_DECRYPT);  
}  
pading = out\[\*out\_len-1\];  
\*(char \*)(out + \*out\_len - pading) = '\\0';

__end__:

return ret;  

}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章