我想使用OpenSSL计算CMAC。我发现this question帮助了我。
但我遇到以下代码的问题:
#include <openssl/cmac.h>
void dispHex(const unsigned char *buffer, unsigned int size) {
int i=0;
for (i=0; i<size-1; i++) {
printf("%02X ", buffer[i]);
}
printf("%02x\n", buffer[i]);
}
int main() {
size_t out_len;
unsigned char res[16];
unsigned char mac_key[16] = { 0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07};
unsigned char msg[16] = { 0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07};
CMAC_CTX *cmac = CMAC_CTX_new();
CMAC_Init(cmac, mac_key, 16, EVP_aes_128_cbc(), NULL);
CMAC_Update(cmac, msg, sizeof(msg));
CMAC_Final(cmac, res, &out_len);
dispHex(res, sizeof(res));
return 0;
}
我使用gcc -o test_cmac test_cmac_openssl.c -L C:/OpenSSL-Win32 -llibeay32 -I C:/OpenSSL-Win32/include
进行编译,它会毫无问题地生成test_cmac.exe
。
但是当我运行它(./test_cmac.exe
)时,没有任何反应。它只是打印一个空行并停止:
xxx@DESKTOP /cygdrive/e/
$ ./test_cmac.exe
xx@DESKTOP /cygdrive/e/
即使我在CMAC计算之前添加printf("...");
,它也会采用相同的方式。
奇怪的是以下程序:
#include <openssl/hmac.h>
void dispHex(const unsigned char *buffer, unsigned int size) {
int i=0;
for (i=0; i<size-1; i++) {
printf("%02X ", buffer[i]);
}
printf("%02X\n", buffer[i]);
}
int main() {
size_t out_len;
unsigned char res[32];
unsigned char mac_key[16] = { 0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07};
unsigned char msg[16] = { 0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07};
HMAC_CTX hmac;
HMAC_CTX_init(&hmac);
HMAC_Init_ex(&hmac, mac_key, 16, EVP_sha256(), NULL);
HMAC_Update(&hmac, msg, sizeof(msg));
HMAC_Final(&hmac, res, &out_len);
dispHex(res, sizeof(res));
return 0;
}
正常运行:在gcc -o test_hmac test_hmac_openssl.c -L C:/OpenSSL-Win32 -llibeay32 -I C:/OpenSSL-Win32/include
和./test_hmac.exe
之后我得到:
xxx@DESKTOP /cygdrive/e/
$ ./test_hmac.exe
...9A 21 F8 2D 60 84 6C 09 08 98 A5 1F 23 8C C8 8F C4 A9 0C C4 49 45 DA 10 B9 39 C0 93 C3 10 60 BE
xxx@DESKTOP /cygdrive/e/
所以我有点困惑...... 为什么它适用于HMAC原语而不适用于CMAC原语?有没有人遇到过这种问题?
我使用的是OpenSSL 32位版本:openssl version
返回OpenSSL 1.0.2e 3 Dec 2015
。
我还检查了在PATH环境变量中声明了C:\OpenSSL-Win32\
。
答案 0 :(得分:2)
查看IMPL
,似乎未执行CMAC对象的初始化,因为NULL
为int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t const EVP_CIPHER *cipher, ENGINE *IMPL)
if (!key && !cipher && !IMPL && keylen == 0) {
/* Not initialised */
if (ctx->nlast_block == -1)
return 0;
if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv))
return 0;
memset(ctx->tbl, 0, EVP_CIPHER_CTX_block_size(ctx->cctx));
ctx->nlast_block = 0;
return 1;
}
:
myNameSpace = {
STATICPROPERTY: 'test',
method: function() {
var variable = 'thisVarIsPrivateToMethod';
this.variable = 'dynamic';
},
init: function() {
this.method();
console.log(this.STATICPROPERTY); // will log "test"
console.log(this.variable); // will log "dynamic"
}
}
myNameSpace.init();
答案 1 :(得分:1)
为什么它适用于HMAC原语而不适用于CMAC原语?有没有人遇到过这种问题?
我猜大多数问题都是由于混合和匹配编译器造成的。当您使用GCC时,Shining Light的Win32 OpenSSL使用Microsoft的编译器。可能还有一些混合和匹配的运行时。
我很惊讶HMAC代码在配置中按预期工作。我猜你很幸运。
以下对我有用,但存在一些差异:
#include <openssl/evp.h>
#include <openssl/cmac.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
void dispHex(const unsigned char *buffer, unsigned int size) {
unsigned int i=0;
for (i=0; i<size; i++) {
printf("%02X ", buffer[i]);
}
printf("\n");
}
int main() {
int rc = 0;
size_t out_len = 0;
unsigned char res[EVP_MAX_MD_SIZE];
unsigned char mac_key[16] = { 0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07};
unsigned char msg[16] = { 0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07};
CMAC_CTX *cmac = CMAC_CTX_new();
assert(cmac != NULL);
rc = CMAC_Init(cmac, mac_key, sizeof(mac_key), EVP_aes_128_cbc(), NULL);
assert(rc == 1);
rc = CMAC_Update(cmac, msg, sizeof(msg));
assert(rc == 1);
rc = CMAC_Final(cmac, res, &out_len);
assert(rc == 1);
dispHex(res, out_len);
CMAC_CTX_free(cmac);
return 0;
}
您的配置与我使用的配置之间存在差异:
res
的大小为EVP_MAX_MD_SIZE
CMAC_Init
使用sizeof(mac_key)
out_len
已初始化displayHex
使用out_len
,而非sizeof(res)
使用sizeof(res)
将打印MAC的16个字节,然后打印16个乱码,因为res
被声明为unsigned char res[32]
。我不认为你那么远,所以记住它。
该程序产生以下结果。我不知道这是否是纠正/预期的结果,但它会产生一个结果并打印出来:
$ ./test.exe
43 91 63 0E 47 4E 75 A6 2D 95 7A 04 1A E8 CC CC
OpenSSL does not support Cygwin-x64,所以你需要使用i686版本的东西。另请参阅OpenSSL Bug Tracker上的Issue #4326: Failed to configure for Cygwin-x64。
以下是如何在Cygwin-x64下构建OpenSSL。 OpenSSL的构建脚本有一些弯曲,因此您无法使用 config
。您必须使用 Configure
并调出三元组。错误跟踪器问题仍然有效,因为config
应该使事情正确。
$ curl https://www.openssl.org/source/openssl-1.0.2f.tar.gz -o openssl-1.0.2f.tar.gz
...
$ tar -xzf openssl-1.0.2f.tar.gz
...
$ cd openssl-1.0.2f
然后:
$ export KERNEL_BITS=64
$ ./Configure Cygwin-x86_64 shared no-ssl2 no-ssl3 --openssldir="$HOME/ssl"
...
$ make depend
...
$ make
...
$ make install_sw
install_sw
在$OPENSSLDIR/include
中安装标头,在$OPENSSLDIR/lib
中安装库。它不会安装手册页。
然后编译并链接:
$ gcc -I "$HOME/ssl/include" test.c -o test.exe "$HOME/ssl/lib/libcrypto.a"
链接libcrypto.a
意味着您可以避免库路径问题。事情将“适合你”。