Пример
В примере не используются дополнительные незашифрованные данные, поэтому параметр [1] для gcry_cipher_ctl, устанавливающий GCRYCTL_SET_CCM_LENGTHS, равен 0. Но при необходимости его можно легко настроить.
Функциональность разделена на три части:
- подготовить (установить ключ, одноразовый номер (IV) и длины CCM)
- функция шифрования
- функция расшифровки
Если вы запустите его, он выведет на консоль следующий текст:
decrypted result: 'VNiJkPzAWPFm1234'
Код
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gcrypt.h>
void error(const char *what, gcry_error_t err) {
fprintf(stderr, "%s failed: %s\n", what, gcry_strerror(err));
exit(1);
}
typedef struct {
const void *key;
const void *nonce;
size_t messageSize;
int authTagLength;
} Config;
void prepare(Config config, gcry_cipher_hd_t *hd) {
gcry_error_t err = gcry_cipher_open(hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CCM, 0);
if (err) { error("gcry_cipher_open", err); }
err = gcry_cipher_setkey(*hd, config.key, strlen(config.key));
if (err) { error("gcry_cipher_setkey", err); }
err = gcry_cipher_setiv(*hd, config.nonce, strlen(config.nonce));
if (err) { error("gcry_cipher_setiv", err); }
uint64_t params[3];
params[0] = config.messageSize;
params[1] = 0;
params[2] = config.authTagLength;
err = gcry_cipher_ctl(*hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof(params));
if (err) { error("gcry_cipher_ctl", err); }
}
void *encrypt(Config config, const void *plainText, void **tag) {
gcry_cipher_hd_t hdEncrypt;
prepare(config, &hdEncrypt);
void *cipherText = malloc(config.messageSize);
gcry_error_t err = gcry_cipher_encrypt(hdEncrypt, cipherText, config.messageSize, plainText, config.messageSize);
if (err) { error("gcry_cipher_encrypt", err); }
*tag = malloc(config.authTagLength);
err = gcry_cipher_gettag(hdEncrypt, *tag, config.authTagLength);
if (err) { error("gcry_cipher_encrypt", err); }
gcry_cipher_close(hdEncrypt);
return cipherText;
}
void *decrypt(Config config, void *cipherText, void *tag) {
gcry_cipher_hd_t hdDecrypt;
prepare(config, &hdDecrypt);
void *recoveredText = malloc(config.messageSize);
gcry_error_t err = gcry_cipher_decrypt(hdDecrypt, recoveredText, config.messageSize, cipherText, config.messageSize);
if (err) { error("gcry_cipher_decrypt", err); }
err = gcry_cipher_checktag(hdDecrypt, tag, config.authTagLength);
if (gpg_err_code (err) == GPG_ERR_CHECKSUM) {
error("Authentication", err);
}
gcry_cipher_close(hdDecrypt);
return recoveredText;
}
int main() {
const char *plainText = "VNiJkPzAWPFm1234";
Config config;
config.key = "1234567890123456";
config.nonce = "0123456789012";
config.messageSize = strlen(plainText) + 1;
config.authTagLength = 10;
void *tag;
void *cipherText = encrypt(config, plainText, &tag);
char *recoveredText = decrypt(config, cipherText, tag);
printf("decrypted result: '%s'\n", recoveredText);
free(tag);
free(cipherText);
free(recoveredText);
return 0;
}