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 <openssl/opensslconf.h> # ifdef OPENSSL_NO_AES
# error AES is disabled.
# endif # include <stddef.h> # 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 <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include "openssl/pem.h"
#include "openssl/bio.h"
#include "openssl/evp.h"
#include "openssl/aes.h"
#include <string.h>
#include <stdio.h> #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;
}

最新文章

  1. SAX解析技术
  2. Java Web 工作技巧总结 16.8
  3. 如何从Windows Phone 生成PDF文档
  4. for之Python vs C#
  5. Qt图片显示效率的比较 转
  6. 依赖注入(DI)有助于应用对象之间的解耦,而面向切面编程(AOP)有助于横切关注点与所影响的对象之间的解耦(转good)
  7. 【C++ Primer每天刷牙】一间 迭代器
  8. HTML5分析实战Web存储机制(Web Storage)
  9. ubuntu14.4 分辨率偏低
  10. Mongodb 相关链接
  11. Redis 数据结构之dict
  12. python全栈开发day36-IO多路复用
  13. Java 之递归遍历目录
  14. Atitit 纯java项目的提升进度大法---通用json dsl接口
  15. 用jquery实现的QQ邮箱里的多收件人选取及其他效果改进版
  16. JQuery对RadioButton和CheckButton的操作
  17. VMwareWorkstation与Device/CredentialGuard不兼容
  18. vue-router路由器的使用
  19. resin服务一直不停重启
  20. flex布局浅谈

热门文章

  1. 记录一次源码扩展案列——FastJson自定义反序列化ValueMutator
  2. shell脚本获取随机数
  3. Selenium之自动化常遇问题
  4. es7.8启动报错 说是主节点没找到
  5. spring boot:给接口增加签名验证(spring boot 2.3.1)
  6. centos8上安装ImageMagick6.9.10并压缩图片生成webp缩略图
  7. ansible通过yum/dnf模块给受控机安装软件(ansible2.9.5)
  8. centos8平台使用ip命令代替ifconfig管理网络
  9. 论文学习笔记 - Classifification of Hyperspectral and LiDAR Data Using Coupled CNNs
  10. 给定 n 个字符串,求有多少字符串是其他字符串的前缀。