我正在做一个需要对大量数据进行身份验证的项目。看来GMAC是为高吞吐量操作而设计的。我只需要消息验证码,不需要加密。
OpenSSL是否具有GMAC API或仅计算GMAC代码的示例?

我知道GCM用于加密和身份验证,但就我而言,不需要加密。是否有仅使用openssl进行GMAC计算的示例?

最佳答案

OpenSSL是否具有GMAC API和示例...


OpenSSL Wiki在EVP Authenticated Encryption and Decryption处具有“身份验证加密”模式示例。

GMAC是GCM模式的特例。来自NIST的Special Publication 800-38D


如果GCM输入仅限于不加密的数据,
由此产生的GCM专业化称为GMAC,
输入数据上的身份验证模式...


因此,您要做的就是将数据发送到“其他身份验证数据(AAD)”通道,而不是纯文本(PT)通道。

这是一个使用NIST GCM Test Vectors中的测试向量的示例。请注意,PT数据为空,仅提供AAD数据:

 [Keylen = 128]
 [IVlen = 96]
 [PTlen = 0]
 [AADlen = 128]
 [Taglen = 128]

 Count = 0
 Key = 77be63708971c4e240d1cb79e8d77feb
 IV = e0e00f19fed7ba0136a797f3
 PT =
 AAD = 7a43ec1d9c0a5a78a0b16533a6213cab
 CT =
 Tag = 209fcc8d3675ed938e9c7166709dd946


这是使用硬编码数据的程序(在OpenSSL GMAC example的Pastebin上):

int rc = 0, unused;
unsigned int i;

byte key[] = { 0x77, 0xbe, 0x63, 0x70, 0x89, 0x71, 0xc4, 0xe2,
               0x40, 0xd1, 0xcb, 0x79, 0xe8, 0xd7, 0x7f, 0xeb };
byte iv[] = { 0xe0, 0xe0, 0x0f, 0x19, 0xfe, 0xd7, 0xba, 0x01,
              0x36, 0xa7, 0x97, 0xf3 };
byte aad[] = { 0x7a, 0x43, 0xec, 0x1d, 0x9c, 0x0a, 0x5a, 0x78,
               0xa0, 0xb1, 0x65, 0x33, 0xa6, 0x21, 0x3c, 0xab };

byte tag[16] = { /* calculated */ };
byte exp[] = { 0x20, 0x9f, 0xcc, 0x8d, 0x36, 0x75, 0xed, 0x93,
               0x8e, 0x9c, 0x71, 0x66, 0x70, 0x9d, 0xd9, 0x46 };

EVP_CIPHER_CTX *ctx = NULL;

ctx = EVP_CIPHER_CTX_new();
ASSERT(ctx != NULL);

rc = EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
ASSERT(rc == 1);

rc = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, sizeof(iv), NULL);
ASSERT(rc == 1);

rc = EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv);
ASSERT(rc == 1);

rc = EVP_EncryptUpdate(ctx, NULL, &unused, aad, sizeof(aad));
ASSERT(rc == 1);

rc = EVP_EncryptFinal_ex(ctx, NULL, &unused);
ASSERT(rc == 1);

rc = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, sizeof(tag), tag);
ASSERT(rc == 1);

printf("Calculated tag:\n  ");
for(i = 0; i < sizeof(tag); i++)
{
    printf("%02x", tag[i]);

    if(i == sizeof(tag) - 1) {
        printf("\n");
    }
}

printf("Expected tag:\n  ");
for(i = 0; i < sizeof(exp); i++)
{
    printf("%02x", exp[i]);

    if(i == sizeof(exp) - 1) {
        printf("\n");
    }
}

if(ctx) {
    EVP_CIPHER_CTX_free(ctx);
}


最后,这是程序的输出:

$ ./t.exe
Calculated tag:
  209fcc8d3675ed938e9c7166709dd946
Expected tag:
  209fcc8d3675ed938e9c7166709dd946

10-05 22:27