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; }
原文:https://www.cnblogs.com/yangxinrui/p/11416275.html