Nginx 開源版編譯安裝教程
阿新 • • 發佈:2022-05-15
任務詳情
在Ubuntu編寫程式碼測試OpenSSL功能,包含Base64,SM2,SM3,SM4演算法的呼叫,然後在OpenEuler中重現
提交程式碼連結和執行結果截圖
加分項:在Windows中重現
在ubuntu編寫程式碼測試openssl功能
base64測試
#include <stdio.h> #include <string.h> #include <openssl/evp.h> #include <openssl/x509.h> void tEVP_Encode() { EVP_ENCODE_CTX *ctx; ctx = EVP_ENCODE_CTX_new(); unsigned char in[1024]; int inl; char out[2048]={0}; int outl; FILE *infp; FILE *outfp; infp = fopen("test.dat","rb"); if(infp == NULL) { printf("Open File \"test.dat\" for Read Err.\n"); return; } outfp = fopen("test.txt","w"); if(outfp == NULL) { printf("Open File \"test.txt\" For Write Err.\n"); return; } EVP_EncodeInit(ctx); printf("file\"Test.dat\" after Base64 coding:\n"); while(1) { inl = fread(in,1,1024,infp); if(inl <= 0) break; EVP_EncodeUpdate(ctx,out,&outl,in,inl); fwrite(out,1,outl,outfp); printf("%s",out); } EVP_EncodeFinal(ctx,out,&outl); fwrite(out,1,outl,outfp); printf("%s",out); fclose(infp); fclose(outfp); printf("file \"Test.dat\" Base64 coding is finish,save to \"test.txt\"檔案.\n\n\n"); } void tEVP_Decode() { EVP_ENCODE_CTX *ctx; ctx = EVP_ENCODE_CTX_new(); char in[1024]; int inl; unsigned char out[1024]; int outl; FILE *infp; FILE *outfp; infp = fopen("test.txt","r"); if(infp == NULL) { printf("Open File \"Test.txt\" for Read Err.\n"); return; } outfp = fopen("test-1.dat","wb"); if(outfp == NULL) { printf("Open File \"test-1.txt\" For Write Err.\n"); return; } EVP_DecodeInit(ctx); printf("start file \"Test.txt\" Base64 decoding...\n\n"); while(1) { inl = fread(in,1,1024,infp); if(inl <= 0) break; EVP_DecodeUpdate(ctx,out,&outl,in,inl); fwrite(out,1,outl,outfp); } EVP_DecodeFinal(ctx,out,&outl); fwrite(out,1,outl,outfp); fclose(infp); fclose(outfp); printf("file \"Test.txt\" Base64 decoding is finish,save as \"test-1.dat\"\n\n\n"); } int main() { tEVP_Encode(); tEVP_Decode(); return 0; }
編譯:gcc -o testbase64 testbase64.c -I /home/wpy/Desktop/20191317/include -L /home/wpy/Desktop/20191317/lib64 -lcrypto -lpthread
執行:
sm2測試
-
生成公私鑰對
-
執行
// sm2_enc.c #include <evp.h> #include <pem.h> #include <stdio.h> #include <string.h> /** * @brief 生成SM2公鑰和私鑰檔案 * * @param pri_file 私鑰檔名 * @param pub_file 公鑰檔名 * @return int 成功返回0,否則返回-1 */ int gen_key(const char* pri_file, const char* pub_file); /** * @brief 從檔案中讀取祕鑰。 * * @param key_file 公鑰或私鑰檔名 * @param type 0讀取公鑰,1讀取私鑰 * @return EVP_PKEY* 成功返回相應的祕鑰,失敗返回NULL */ EVP_PKEY* read_key_bio(const char* key_file, const int type); /** * @brief 加密資料 * * @param key 加密公鑰 * @param out 加密密文 * @param in 要加密的資料 * @param inlen 資料長度 * @return size_t 密文長度 */ size_t do_encrypt(EVP_PKEY* key, unsigned char* out, const unsigned char* in, size_t inlen); /** * @brief 解密資料 * * @param key 解密私鑰 * @param out 解密後的資料 * @param in 要解密的資料 * @param inlen 資料長度 * @return size_t 解密後的資料長度 */ size_t do_decrypt(EVP_PKEY* key, unsigned char* out, const unsigned char* in, size_t inlen); int main(int argc, char const* argv[]) { size_t ret; const char* pub_file = "/home/wpy/Desktop/openssl_1/test_sm2_pub_key.pem"; const char* pri_file = "/home/wpy/Desktop/openssl_1/test_sm2_pri.pem"; // 生成公鑰和私鑰並寫入檔案中 if (gen_key(pri_file, pub_file)) { printf("gen key failed."); exit(1); } // 讀取公鑰和私鑰 EVP_PKEY* pub_key = read_key_bio(pub_file, 0); EVP_PKEY* pri_key = read_key_bio(pri_file, 1); unsigned char data[]= "hello 20191317wpy!"; unsigned char enc_txt[BUFSIZ] = {0}; unsigned char dec_txt[BUFSIZ] = {0}; printf("data= %s\n", data); // 公鑰加密 ret = do_encrypt(pub_key, enc_txt, data, strlen((const char*)data)); printf("ret=%ld, enc= ", ret); for (size_t i = 0; i < ret; i++){ printf("%2X", enc_txt[i]); } // 私鑰解密 ret = do_decrypt(pri_key, dec_txt, enc_txt, ret); dec_txt[ret] = 0; printf("\nret=%ld, dec= %s\n", ret, dec_txt); EVP_PKEY_free(pub_key); EVP_PKEY_free(pri_key); return 0; } int gen_key(const char* pri_file, const char* pub_file) { EC_KEY* eckey = EC_KEY_new_by_curve_name(NID_sm2); EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_sm2); EC_KEY_set_group(eckey, group); BIO* param = BIO_new_file("/tmp/param.cache", "w"); PEM_write_bio_ECPKParameters(param, group); EC_KEY_generate_key(eckey); BIO* prikey = BIO_new_file(pri_file, "w"); BIO* pubkey = BIO_new_file(pub_file, "w"); PEM_write_bio_ECPrivateKey(prikey, eckey, NULL, NULL, 0, NULL, NULL); PEM_write_bio_EC_PUBKEY(pubkey, eckey); BIO_free(param); BIO_free(prikey); BIO_free(pubkey); return 0; } EVP_PKEY* read_key_bio(const char* key_file, const int type) { BIO* bio = BIO_new_file(key_file, "r"); EVP_PKEY* key = EVP_PKEY_new(); if (0 == type) { key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); } else { key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); } EVP_PKEY_set_alias_type(key, EVP_PKEY_SM2); BIO_free(bio); return key; } size_t do_encrypt(EVP_PKEY* key, unsigned char* out, const unsigned char* in, size_t inlen) { size_t ret = 0; EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(key, NULL); EVP_PKEY_encrypt_init(ctx); EVP_PKEY_encrypt(ctx, out, &ret, in, inlen); EVP_PKEY_CTX_free(ctx); return ret; } size_t do_decrypt(EVP_PKEY* key, unsigned char* out, const unsigned char* in, size_t inlen) { size_t ret = inlen; EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(key, NULL); EVP_PKEY_decrypt_init(ctx); EVP_PKEY_decrypt(ctx, out, &ret, in, inlen); EVP_PKEY_CTX_free(ctx); return ret; }
sm3測試
#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/err.h> #include <openssl/evp.h> void tDigest() { unsigned char md_value[EVP_MAX_MD_SIZE]; int md_len, i; EVP_MD_CTX *mdctx; char msg1[] = "20191317wpy"; char msg2[] = "wpy20191317"; mdctx = EVP_MD_CTX_new(); EVP_MD_CTX_init(mdctx); EVP_DigestInit_ex(mdctx, EVP_sm3(), NULL); EVP_DigestUpdate(mdctx, msg2, strlen(msg2)); EVP_DigestFinal_ex(mdctx, md_value, &md_len); EVP_MD_CTX_free(mdctx); printf("原始資料%s的摘要值為:\n",msg2); for ( i = 0; i < md_len; i++) { printf("0x%02x ", md_value[i]); } printf("\n"); } int main() { OpenSSL_add_all_algorithms(); tDigest(); return 0; }
-
編譯執行:
sm4測試
/** 檔名: https://github.com/liuqun/openssl-sm4-demo/blob/cmake/src/main.c */
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "openssl/err.h"
#include "openssl/evp.h"
/* Before OpenSSL 1.1.1-pre1, we did not have EVP_sm4_ofb() */
#if defined(OPENSSL_VERSION_NUMBER) \
&& OPENSSL_VERSION_NUMBER < 0x10101001L
static const EVP_CIPHER *(*EVP_sm4_ofb)()=EVP_aes_128_ecb;
#endif
typedef struct {
const unsigned char *in_data;
size_t in_data_len;
int in_data_is_already_padded;
const unsigned char *in_ivec;
const unsigned char *in_key;
size_t in_key_len;
} test_case_t;
void test_encrypt_with_cipher(const test_case_t *in, const EVP_CIPHER *cipher)
{
unsigned char *out_buf = NULL;
int out_len;
int out_padding_len;
EVP_CIPHER_CTX *ctx;
ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, cipher, NULL, in->in_key, in->in_ivec);
if (in->in_data_is_already_padded)
{
/* Check whether the input data is already padded.
And its length must be an integral multiple of the cipher's block size. */
const size_t bs = EVP_CIPHER_block_size(cipher);
if (in->in_data_len % bs != 0)
{
printf("ERROR-1: data length=%d which is not added yet; block size=%d\n", (int) in->in_data_len, (int) bs);
/* Warning: Remember to do some clean-ups */
EVP_CIPHER_CTX_free(ctx);
return;
}
/* Disable the implicit PKCS#7 padding defined in EVP_CIPHER */
EVP_CIPHER_CTX_set_padding(ctx, 0);
}
out_buf = (unsigned char *) malloc(((in->in_data_len>>4)+1) << 4);
out_len = 0;
EVP_EncryptUpdate(ctx, out_buf, &out_len, in->in_data, in->in_data_len);
if (1)
{
printf("Debug: out_len=%d\n", out_len);
}
out_padding_len = 0;
EVP_EncryptFinal_ex(ctx, out_buf+out_len, &out_padding_len);
if (1)
{
printf("Debug: out_padding_len=%d\n", out_padding_len);
}
EVP_CIPHER_CTX_free(ctx);
if (1)
{
int i;
int len;
len = out_len + out_padding_len;
for (i=0; i<len; i++)
{
printf("%02x ", out_buf[i]);
}
printf("\n");
}
if (out_buf)
{
free(out_buf);
out_buf = NULL;
}
}
void main()
{
int have_sm4 = (OPENSSL_VERSION_NUMBER >= 0x10101001L);
int have_aes = 1;
const unsigned char data[]=
{
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
};
unsigned char ivec[EVP_MAX_IV_LENGTH]; ///< IV 向量
const unsigned char key1[16] = ///< key_data, 金鑰內容, 至少16位元組
{
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
};
test_case_t tc;
tc.in_data = data;
tc.in_data_len = sizeof(data);
tc.in_data_is_already_padded = (tc.in_data_len % 16)==0; // Hard coded 16 as the cipher's block size
tc.in_key = key1;
tc.in_key_len = sizeof(key1);
memset(ivec, 0x00, EVP_MAX_IV_LENGTH);
tc.in_ivec = ivec;
#if defined(OPENSSL_NO_SM4)
have_sm4 = 0;
#endif
if (have_sm4)
{
printf("[1]\n");
printf("Debug: EVP_sm4_ofb() test\n");
test_encrypt_with_cipher(&tc, EVP_sm4_ofb());
}
#if defined(OPENSSL_NO_AES)
have_aes = 0;
#endif
if (have_aes)
{
printf("[2]\n");
printf("Debug: EVP_aes_128_ecb() test\n");
test_encrypt_with_cipher(&tc, EVP_aes_128_ecb());
}
}
-
編譯執行
openeuler下編譯執行openssl測試程式碼
base64
sm3
sm4
windows下的openssl測試程式碼執行
base64
gcc -o testsm4 testsm4.c -I /usr/local/openssl/include -L /usr/local/openssl/lib64 -lcrypto -lpthread