cmd
AF_ALG是Linux提供的一种虚拟接口,用于访问内核中的加密算法。在Linux中,可以使用AF_ALG接口配合加密算法框架(Crypto API)来进行加密操作。
以下是一个使用AF_ALG和openssl进行加密操作的例子:
# 加密
openssl engine -t afalg -k afalg -c
# 加载AF_ALG引擎
openssl engine afalg
# 设置会话使用的加密算法和密钥
openssl ciphers -v 'aes-128-cbc'
# 加密文件
openssl enc -engine afalg -aes-128-cbc -in input.txt -out output.txt -pass pass:YOUR_PASSWORD
在这个例子中,我们首先加载AF_ALG加密引擎。然后,我们设置会话使用的加密算法为AES-128-CBC。最后,我们使用openssl的enc命令进行加密操作,指定输入文件input.txt和输出文件output.txt,并使用密钥mysecretkey进行加密。
注意:在使用AF_ALG引擎之前,你需要确保系统中已经安装了libafalg-dev包,并且你的内核支持AF_ALG。
这只是一个基本的示例,实际使用时可能需要根据具体的加密算法和系统配置进行调整。
测试实例:(这是在101编译服务器环境上测试的)
der@somewhere:~/tmp/tmp$ openssl engine -t afalg -k afalg -c
engine: Cannot mix flags and engine names.
engine: Use -help for summary.
der@somewhere:~/tmp/tmp$ openssl engine -t afalg -k afalg
engine: Cannot mix flags and engine names.
engine: Use -help for summary.
der@somewhere:~/tmp/tmp$ openssl engine -t afalg
(afalg) AFALG engine support
[ available ]
der@somewhere:~/tmp/tmp$
der@somewhere:~/tmp/tmp$
der@somewhere:~/tmp/tmp$ openssl engines
Invalid command 'engines'; type "help" for a list.
der@somewhere:~/tmp/tmp$ openssl engine
(rdrand) Intel RDRAND engine
(dynamic) Dynamic engine loading support
der@somewhere:~/tmp/tmp$ openssl engine afalg
(afalg) AFALG engine support
der@somewhere:~/tmp/tmp$ openssl ciphers -v 'aes-128-cbc'
TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD
TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any Au=any Enc=CHACHA20/POLY1305(256) Mac=AEAD
TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD
der@somewhere:~/tmp/tmp$
der@somewhere:~/tmp/tmp$ find /usr/lib -name "*afalg*"
/usr/lib/x86_64-linux-gnu/engines-1.1/afalg.so
der@somewhere:~/tmp/tmp$
der@somewhere:~/tmp/tmp$ openssl enc -engine afalg -aes-128-cbc -in info.txt -out output.txt
engine "afalg" set.
enter aes-128-cbc encryption password:
Verifying - enter aes-128-cbc encryption password:
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
der@somewhere:~/tmp/tmp$
der@somewhere:~/tmp/tmp$
der@somewhere:~/tmp/tmp$ openssl enc -d -engine afalg -aes-128-cbc -in output.txt -out dec.txt -pass pass:somepasswd
engine "afalg" set.
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
der@somewhere:~/tmp/tmp$
der@somewhere:~/tmp/tmp$ md5sum info.txt dec.txt
c50829378ad3f6ad668b290ef8b17cc4 info.txt
c50829378ad3f6ad668b290ef8b17cc4 dec.txt
der@somewhere:~/tmp/tmp$
code
加载
int main() {
int ret = 1;
int type = 0;
do{
printf("please choose type: 0:exit 1:load_builtin, 2:init_crypto AFALG, 3:init_crypto DYNAMIC, 4:add_all_algorithms\n");
(void)scanf(" %d",&type);
switch(type){
case 0:
return 0;
case 1:
ENGINE_load_builtin_engines();
break;
case 2:
OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_AFALG, NULL);
break;
case 3:
OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_DYNAMIC, NULL);
break;
case 4:
OpenSSL_add_all_algorithms();
break;
}
ENGINE *e = ENGINE_by_id("afalg");
if (e == NULL) {
printf("Can not load AFALG engine.\n");
continue;
}
printf("Load AFALG engine OK.\n");
int rc = ENGINE_init(e);
if (rc == 0) {
printf("Init AFALG engine fail.\n");
ENGINE_free(e);
continue;
}
printf("Init AFALG engine OK.\n");
//now we can use afalg engine
第1种第3种可以加载,2,4种不行
使用
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/engine.h>
// colors used in printf
#define COLOR_NONE "\033[m"
#define COLOR_RED "\033[0;32;31m"
#define COLOR_LIGHT_RED "\033[1;31m"
#define COLOR_YELLOW "\033[1;33m"
#define COLOR_GREEN "\033[0;32;32m"
#define COLOR_BLUE "\033[0;32;34m"
#define COLOR_PURPLE "\033[0;32;35m"
// switch of printf
#if 1
#define PRINT(...) printf(__VA_ARGS__)
#else
#define PRINT(...)
#endif
#if 0
#define PRINTSUCCESS(...) printf(__VA_ARGS__)
#else
#define PRINTSUCCESS(...)
#endif
#if 1
#define PRINTFAIL(...) printf(__VA_ARGS__)
#else
#define PRINTFAIL(...)
#endif
// macros related to break
#define FREE_NOTNULL(ptr, func_name) \
{ \
if (ptr != NULL) \
{ \
func_name(ptr); \
ptr = NULL; \
} \
}
#define CALL_FUNC(ret, funSentence, errCase) \
{ \
ret = funSentence; \
if (errCase) \
{ \
PRINTFAIL(COLOR_RED "[%s][%d] " #funSentence " fail:" #errCase "\n" COLOR_NONE, __FILE__, __LINE__); \
break; \
} \
else \
{ \
PRINTSUCCESS(COLOR_GREEN "[%s][%d] " #funSentence " success\n" COLOR_NONE, __FILE__, __LINE__); \
} \
}
#define CALL_FUNC_WITHIOUTBREAK(ret, funSentence, errCase) \
{ \
ret = funSentence; \
if (errCase) \
{ \
PRINTFAIL(COLOR_RED "[%s][%d] " #funSentence " fail:" #errCase "\n" COLOR_NONE, __FILE__, __LINE__); \
} \
else \
{ \
PRINTSUCCESS(COLOR_GREEN "[%s][%d] " #funSentence " success\n" COLOR_NONE, __FILE__, __LINE__); \
} \
}
#define CALL_FUNC_NOTNULL(ret, funSentence) \
CALL_FUNC(ret, funSentence, ret == NULL)
#define CALL_FUNC_POSITIVE(ret, funSentence) \
CALL_FUNC(ret, funSentence, ret <= 0)
#define CALL_NBFUNC_NOTNULL(ret, funSentence) \
CALL_FUNC_WITHIOUTBREAK(ret, funSentence, ret == NULL)
#define CALL_NBFUNC_POSITIVE(ret, funSentence) \
CALL_FUNC_WITHIOUTBREAK(ret, funSentence, ret <= 0)
#define BUFFER_SIZE 256
static void print_hex(const char *info, unsigned char *data, unsigned int len)
{
printf("%s[len:%d | 0x%x]\n", info, len, len);
for (int i = 0; i < len; i++)
{
printf("%02x ", data[i]);
}
printf("\n");
}
static int test_afalg_aes_cbc(ENGINE *engine)
{
EVP_CIPHER_CTX *ctx = NULL;
const EVP_CIPHER *cipher;
unsigned char key[] = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
"\x51\x2e\x03\xd5\x34\x12\x00\x06"
"\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
"\x51\x2e\x03\xd5\x34\x12\x00\x06";
unsigned char iv[] = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
"\xb4\x22\xda\x80\x2c\x9f\xac\x41";
/* input = "Single block msg\n" 17Bytes*/
unsigned char in[BUFFER_SIZE] = "\x53\x69\x6e\x67\x6c\x65\x20\x62"
"\x6c\x6f\x63\x6b\x20\x6d\x73\x67\x0a";
unsigned char ebuf[BUFFER_SIZE + 32];
unsigned char dbuf[BUFFER_SIZE + 32];
unsigned char encresult_128[] = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
"\x27\x08\x94\x2d\xbe\x77\x18\x1a\x2d";
unsigned char encresult_192[] = "\xf7\xe4\x26\xd1\xd5\x4f\x8f\x39"
"\xb1\x9e\xe0\xdf\x61\xb9\xc2\x55\xeb";
unsigned char encresult_256[] = "\xa0\x76\x85\xfd\xc1\x65\x71\x9d"
"\xc7\xe9\x13\x6e\xae\x55\x49\xb4\x13";
unsigned char *enc_result = NULL;
int encl, encf, decl, decf;
int ret = 0;
int keysize_idx = 0;
printf("please choose key len: 0:128, 1:192, 2:256 else:128\n");
(void)scanf(" %d", &keysize_idx);
do
{
switch (keysize_idx)
{
case 0:
cipher = EVP_aes_128_cbc();
enc_result = &encresult_128[0];
break;
case 1:
cipher = EVP_aes_192_cbc();
enc_result = &encresult_192[0];
break;
case 2:
cipher = EVP_aes_256_cbc();
enc_result = &encresult_256[0];
break;
default:
cipher = EVP_aes_128_cbc();
enc_result = &encresult_128[0];
break;
}
CALL_FUNC_NOTNULL(ctx, EVP_CIPHER_CTX_new())
print_hex("src data", in, BUFFER_SIZE);
CALL_FUNC_POSITIVE(ret, EVP_CipherInit_ex(ctx, cipher, engine, key, iv, 1))
CALL_FUNC_POSITIVE(ret, EVP_CipherUpdate(ctx, ebuf, &encl, in, BUFFER_SIZE))
CALL_FUNC_POSITIVE(ret, EVP_CipherFinal_ex(ctx, ebuf + encl, &encf))
encl += encf;
print_hex("enc data", ebuf, encl);
// CALL_FUNC(ret,memcmp(enc_result, ebuf, BUFFER_SIZE),ret != 0)
CALL_FUNC_POSITIVE(ret, EVP_CIPHER_CTX_reset(ctx))
CALL_FUNC_POSITIVE(ret, EVP_CipherInit_ex(ctx, cipher, engine, key, iv, 0))
CALL_FUNC_POSITIVE(ret, EVP_CipherUpdate(ctx, dbuf, &decl, ebuf, encl))
CALL_FUNC_POSITIVE(ret, EVP_CipherFinal_ex(ctx, dbuf + decl, &decf))
print_hex("dec data", dbuf, decl);
decl += decf;
CALL_FUNC_POSITIVE(ret, decl == BUFFER_SIZE)
CALL_FUNC(ret, memcmp(dbuf, in, BUFFER_SIZE), ret != 0)
printf("engine enc dec success.\n");
ret = 1;
} while (0);
end:
FREE_NOTNULL(ctx, EVP_CIPHER_CTX_free)
return ret;
}
int test_engine_digest(ENGINE *engine)
{
int ret = 0;
const EVP_MD *md = NULL;
EVP_MD_CTX *emctx = NULL;
unsigned char data[128] = {1, 2, 4};
unsigned char digestData[64] = {0};
unsigned int digestSize = sizeof(digestData);
const char *eName = NULL;
do
{
CALL_FUNC_NOTNULL(eName, ENGINE_get_name(engine))
printf("engine name:%s\n", eName);
CALL_FUNC_POSITIVE(ret, ENGINE_register_digests(engine)) //
CALL_FUNC_POSITIVE(ret, ENGINE_set_default(engine, ENGINE_METHOD_ALL)) // ENGINE_METHOD_DIGESTS))
CALL_FUNC_NOTNULL(emctx, EVP_MD_CTX_new())
CALL_FUNC_POSITIVE(ret, EVP_MD_CTX_init(emctx))
CALL_FUNC_NOTNULL(md, EVP_md5())
digestSize = sizeof(digestData);
CALL_FUNC_POSITIVE(ret, EVP_DigestInit_ex(emctx, md, engine))
CALL_FUNC_POSITIVE(ret, EVP_DigestUpdate(emctx, data, sizeof(data)))
CALL_FUNC_POSITIVE(ret, EVP_DigestFinal(emctx, digestData, &digestSize))
print_hex("MD5 3 segment result", digestData, digestSize);
memset(digestData, 0, sizeof(digestData));
digestSize = sizeof(digestData);
// CALL_FUNC_POSITIVE(ret,EVP_DigestInit_ex(emctx,md,engine))
CALL_FUNC_POSITIVE(ret, EVP_Digest(data, sizeof(data), digestData, &digestSize, md, engine))
print_hex("MD5 1 segment result", digestData, digestSize);
memset(digestData, 0, sizeof(digestData));
digestSize = sizeof(digestData);
CALL_FUNC_NOTNULL(md, EVP_sha1())
CALL_FUNC_POSITIVE(ret, EVP_DigestInit_ex(emctx, md, engine))
CALL_FUNC_POSITIVE(ret, EVP_DigestUpdate(emctx, data, sizeof(data)))
CALL_FUNC_POSITIVE(ret, EVP_DigestFinal(emctx, digestData, &digestSize))
print_hex("SHA1 3 segment result", digestData, digestSize);
memset(digestData, 0, sizeof(digestData));
digestSize = sizeof(digestData);
CALL_FUNC_NOTNULL(md, EVP_sha256())
CALL_FUNC_POSITIVE(ret, EVP_DigestInit_ex(emctx, md, engine))
CALL_FUNC_POSITIVE(ret, EVP_DigestUpdate(emctx, data, sizeof(data)))
CALL_FUNC_POSITIVE(ret, EVP_DigestFinal(emctx, digestData, &digestSize))
print_hex("SHA256 3 segment result", digestData, digestSize);
} while (0);
// FREE_NOTNULL(md,EVP_md5xx) //do not need free
FREE_NOTNULL(emctx, EVP_MD_CTX_free)
return ret;
}
int main()
{
int ret = 1;
int type = 0;
do
{
printf("please choose type: 0:exit 1:load_builtin, 2:init_crypto AFALG, 3:init_crypto DYNAMIC, 4:add_all_algorithms\n");
(void)scanf(" %d", &type);
switch (type)
{
case 0:
return 0;
case 1:
ENGINE_load_builtin_engines();
break;
case 2:
OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_AFALG, NULL);
break;
case 3:
OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_DYNAMIC, NULL);
break;
case 4:
OpenSSL_add_all_algorithms();
break;
}
ENGINE *e = ENGINE_by_id("afalg");
if (e == NULL)
{
printf("Can not load AFALG engine.\n");
continue;
}
printf("Load AFALG engine OK.\n");
int rc = ENGINE_init(e);
if (rc == 0)
{
printf("Init AFALG engine fail.\n");
ENGINE_free(e);
continue;
}
printf("Init AFALG engine OK.\n");
// now we can use afalg engine
CALL_FUNC_POSITIVE(ret, test_afalg_aes_cbc(e))
CALL_FUNC_POSITIVE(ret, test_engine_digest(e))
// ENGINE_free(e);
ENGINE_finish(e);
} while (type != 0);
return 0;
}
der@somewhere:~/tmp/tmp/engine$ gcc -o engine engine.c -lcrypto
der@somewhere:~/tmp/tmp/engine$ ./engine
please choose type: 0:exit 1:load_builtin, 2:init_crypto AFALG, 3:init_crypto DYNAMIC, 4:add_all_algorithms
3
Load AFALG engine OK.
Init AFALG engine OK.
please choose key len: 0:128, 1:192, 2:256 else:128
2
src data[len:256 | 0x100]
53 69 6e 67 6c 65 20 62 6c 6f 63 6b 20 6d 73 67 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
enc data[len:272 | 0x110]
a0 76 85 fd c1 65 71 9d c7 e9 13 6e ae 55 49 b4 ca 9f 86 f1 4f 52 d9 66 6c a1 f9 25 ae 42 c6 d9 e6 f2 15 3a 08 14 c2 e0 02 06 de e2 c1 45 ba 02 dc 36 85 a8 2e 74 a3 68 b8 96 69 0f 78 59 34 50 77 85 24 00 f1 54 ea 9f 75 b7 61 c1 db a1 ad b3 3b b5 c1 c9 77 9f f0 f8 fc 95 f1 36 17 34 c5 03 41 43 1e 6e 69 e8 e1 88 fb d1 ac 0c 46 6e 71 26 52 a3 91 b3 87 dc 6a 16 e4 02 a8 a4 8b 4c 6a c1 ef 5d 92 3b ab 43 cc 80 34 5a c6 52 c6 48 8b a0 f5 14 12 85 55 78 92 80 30 5f f9 45 e1 fe 61 e9 02 da a1 69 19 a1 92 16 87 f2 a3 8d e3 e8 15 34 69 c2 40 69 2b 15 43 27 da 4e 56 15 d3 10 e5 55 58 8c d0 0e ee 2b 3f 00 57 e8 65 7f ac d5 01 af 9a 13 1a c0 ae ac b1 a8 01 46 f7 15 2d 26 22 b1 87 a0 ee db a3 fb 9d a3 94 77 91 e1 72 25 5e 9c 17 d6 d6 5f e9 3c 2f 0f bb be 79 1f 99 06 7e 37 68 67 9c 76 04 dc de e3 dc ed dd c9 32 fd dc 7d
dec data[len:256 | 0x100]
53 69 6e 67 6c 65 20 62 6c 6f 63 6b 20 6d 73 67 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
engine enc dec success.
engine name:AFALG engine support
[engine.c][197] EVP_DigestInit_ex(emctx,md,engine) fail:ret <= 0
[engine.c][271] test_engine_digest(e) fail:ret <= 0
der@somewhere:~/tmp/tmp/engine$
der@somewhere:~/tmp/tmp/engine$
可以看到aes使用afalg引擎成功,但是digest使用引擎失败了。之前好像看到过说明,digest软算法很快,如果使用硬件加速引擎综合开销反而更大或者效率提升不明显,如果需要引擎支持digest需要编译openssl的时候指定相应标志。就这样。