加解密 C语言实现
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;
}
加解密 C语言实现的更多相关文章
- 3DES加解密 C语言
3DES(或称为Triple DES),它相当于是对每个数据块应用三次DES加密算法.3*8字节密钥. 设Ek()和Dk()代表DES算法的加密和解密过程,K代表DES算法使用的密钥,P代表明文,C代 ...
- 【go语言】RSA加解密
关于go语言的RSA加解密的介绍,这里有一篇文章,已经介绍的很完整了. 对应的go语言的加解密代码,参考git. 因为原文跨语言是跟php,我这里要跟c语言进行交互,所以,这里贴上c语言的例子. 参考 ...
- 与非java语言使用RSA加解密遇到的问题:algid parse error, not a sequence
遇到的问题 在一个与Ruby语言对接的项目中,决定使用RSA算法来作为数据传输的加密与签名算法.但是,在使用Ruby生成后给我的私钥时,却发生了异常:IOException: algid parse ...
- openssl在多平台和多语言之间进行RSA加解密注意事项
首先说一下平台和语言: 系统平台为CentOS6.3,RSA加解密时使用NOPADDING进行填充 1)使用C/C++调用系统自带的openssl 2)Android4.2模拟器,第三方openssl ...
- L脚本语言实现文件加解密
L脚本语言中能够对内存对象进行AES加解密.我们能够非常easy地实现文件加解密 #scp #定义一个秘钥字符串 定义:字符串,str1,abcdefg 打开:文件,file1,c:\1.txt 打开 ...
- DES加解密算法(C语言实现)
DES加密和解密算法的实现(C语言) 主要是做个记录,害怕以后代码丢了,先放到这里了. DES再不进行介绍了,可以看上一篇的 DES 的python实现 转载请注明出处:https://www.cnb ...
- 实验一:C语言实现DES加解密算法
计算程序执行10万次需要的时间: 总共需要175秒 加解密一次的时间小于:0.00175秒 纯计算加解密的时间会更短 去除IO操作后的时间 也就是说加解密一次的时间为0.07毫秒 /*-------- ...
- Go语言加解密--AES简单实践
AES加解密的简单实现,代码如下. package main import ( "crypto/aes" "crypto/cipher" "encod ...
- rsa互通密钥对生成及互通加解密(c#,java,php)
摘要 在数据安全上rsa起着非常大的作用,特别是数据网络通讯的安全上.当异构系统在数据网络通讯上对安全性有所要求时,rsa将作为其中的一种选择,此时rsa的互通性就显得尤为重要了. 本文参考网络资料, ...
随机推荐
- MeteoInfo家族的新产品:MeteoInfoLab
为了更方便地处理各种数据并绘图,尝试开发了一个新的软件产品MeteoInfoLab,软件设计上参考了MatLab和Spider.软件以脚本程序和命令行交互为主,基于MeteoInfo库并利用Jytho ...
- Verilog基础入门——简单的语句块编写(一)
[题干] [代码] module top_module ( input in, output out ); assign out = ~in; endmodule 简单的实现一个非门
- go语言安装使用
go语言安装使用 下载地址 https://golang.google.cn/dl/ https://studygolang.com/dl windows https://studygolang.co ...
- 【差分】POJ 3263 Tallest Cow
题目大意 POJ链接 给出\(n\)头牛的身高,和\(m\)对关系,表示牛\(a[i]\)与\(b[i]\)可以相互看见.已知最高的牛为第\(p\)头,身高为\(h\). 求每头牛的身高最大可能是多少 ...
- go 结构体函数
package main import "fmt" type Dog struct { Name string } func (d *Dog) speak() string { r ...
- Golang数组和切片的区别
大纲 数组是固定大小 切片不是动态数组,可以扩容 区别 定义方式不一样 初始化方法不一样 package main import "fmt" func main() { // -- ...
- CentOS8安装本地mail工具-mailx-12.5-29.el8.x86_64
概述 服务器需要发告警邮件 查找是否已安装 [root@C8-1 ~]# type mail -bash: type: mail: not found [root@C8-1 ~]# which mai ...
- java: 非法字符: '\ufeff'
错误问题记录: Error:(1, 1) java: 非法字符: '\ufeff' Error:(1, 1) 错误: 需要class, interface或enum报错 问题发生时因为编码问题导致,如 ...
- Git版本管理器操作步骤
组长建立管理器: 第一步: 管理器网址:https://gitee.com/ 第二步:注册个人信息 第三步(添加项目) 第四步(兴建文件)注意:必须双层文件夹 第五步:打开VS开发工具 第六步:去把刚 ...
- 创建Sqlite数据库(一)
对这方面的掌握不牢,慢慢深入吧,先执行一个sqlite语句,只会简单的.输出"创建"证明创建成功 public class MainActivity extends AppComp ...