diff options
-rw-r--r-- | ChangeLog.adoc | 1 | ||||
-rw-r--r-- | doc/en/weechat_plugin_api.en.adoc | 43 | ||||
-rw-r--r-- | doc/fr/weechat_plugin_api.fr.adoc | 44 | ||||
-rw-r--r-- | doc/it/weechat_plugin_api.it.adoc | 44 | ||||
-rw-r--r-- | doc/ja/weechat_plugin_api.ja.adoc | 44 | ||||
-rw-r--r-- | doc/sr/weechat_plugin_api.sr.adoc | 46 | ||||
-rw-r--r-- | src/core/wee-crypto.c | 100 | ||||
-rw-r--r-- | src/core/wee-crypto.h | 2 | ||||
-rw-r--r-- | src/plugins/plugin-api.c | 30 | ||||
-rw-r--r-- | src/plugins/plugin-api.h | 3 | ||||
-rw-r--r-- | src/plugins/plugin.c | 1 | ||||
-rw-r--r-- | src/plugins/weechat-plugin.h | 8 | ||||
-rw-r--r-- | tests/unit/core/test-core-crypto.cpp | 69 |
13 files changed, 432 insertions, 3 deletions
diff --git a/ChangeLog.adoc b/ChangeLog.adoc index bdd3f1bee..164941fd7 100644 --- a/ChangeLog.adoc +++ b/ChangeLog.adoc @@ -24,6 +24,7 @@ New features:: * core: add option weechat.look.highlight_disable_regex and buffer property "highlight_disable_regex" (issue #1798) * api: rename function string_build_with_split_string to string_rebuild_split_string, add arguments "index_start" and "index_end" * api: add info "uptime_current" + * api: add function crypto_hash_file * buflist: add variable `${hotlist_priority_number}` (integer version of `${hotlist_priority}`) * irc: display SETNAME command in channels and private buffers, add options irc.color.message_setname and irc.look.smart_filter_setname (issue #1805) * trigger: add elapsed time for trigger execution on monitor buffer when trigger debug is set, add option trigger.color.identifier (issue #1806) diff --git a/doc/en/weechat_plugin_api.en.adoc b/doc/en/weechat_plugin_api.en.adoc index 6ac9e5440..7f69e8a67 100644 --- a/doc/en/weechat_plugin_api.en.adoc +++ b/doc/en/weechat_plugin_api.en.adoc @@ -3751,6 +3751,49 @@ rc = weechat_crypto_hash (data, strlen (data), "sha256", hash, &hash_size); [NOTE] This function is not available in scripting API. +==== crypto_hash_file + +_WeeChat ≥ 3.7._ + +Compute hash of a file. + +Prototype: + +[source,c] +---- +int weechat_crypto_hash_file (const char *filename, const char *hash_algo, + void *hash, int *hash_size); +---- + +Arguments: + +* _filename_: path and file name +* _hash_algo_: the hash algorithm, see table in function + <<crypto_hash_algorithms,crypto_hash>> +* _hash_: pointer to the hash variable, which is used to store the resulting hash + (the buffer must be large enough, according to the algorithm, see table in + function <<crypto_hash_algorithms,crypto_hash>>) +* _hash_size_: pointer to a variable used to store the size of the hash computed + (in bytes) (can be NULL) + +Return value: + +* 1 if OK, 0 if error + +C example: + +[source,c] +---- +char hash[256 / 8]; +int rc, hash_size; +rc = weechat_crypto_hash_file ("/path/to/file", "sha256", hash, &hash_size); +/* rc == 1, hash_size == 32 and hash is a buffer with: + 71 c4 80 df 93 d6 ae 2f 1e fa d1 44 7c 66 c9 52 5e 31 62 18 cf 51 fc 8d 9e d8 32 f2 da f1 8b 73 */ +---- + +[NOTE] +This function is not available in scripting API. + ==== crypto_hash_pbkdf2 _WeeChat ≥ 2.8._ diff --git a/doc/fr/weechat_plugin_api.fr.adoc b/doc/fr/weechat_plugin_api.fr.adoc index 6b74e6c6a..13ccac44f 100644 --- a/doc/fr/weechat_plugin_api.fr.adoc +++ b/doc/fr/weechat_plugin_api.fr.adoc @@ -3812,6 +3812,50 @@ rc = weechat_crypto_hash (data, strlen (data), "sha256", hash, &hash_size); [NOTE] Cette fonction n'est pas disponible dans l'API script. +==== crypto_hash_file + +_WeeChat ≥ 3.7._ + +Calculer le hachage d'un fichier. + +Prototype : + +[source,c] +---- +int weechat_crypto_hash_file (const char *filename, const char *hash_algo, + void *hash, int *hash_size); +---- + +Paramètres : + +* _filename_ : chemin et nom du fichier +* _hash_algo_ : l'algorithme de hachage, voir le tableau de la fonction + <<crypto_hash_algorithms,crypto_hash>> +* _hash_ : pointeur vers la variable de hachage, qui est utilisée pour stocker + le résultat du hachage (le tampon doit être suffisamment grand, selon + l'algorithme, voir le tableau de la fonction + <<crypto_hash_algorithms,crypto_hash>>) +* _hash_size_ : pointeur vers une variable utiliser pour stocker la longueur + du résultat du hachage (en octets) (peut être NULL) + +Valeur de retour : + +* 1 si OK, 0 si erreur + +Exemple en C : + +[source,c] +---- +char hash[256 / 8]; +int rc, hash_size; +rc = weechat_crypto_hash_file ("/chemin/vers/fichier", "sha256", hash, &hash_size); +/* rc == 1, hash_size == 32 et hash est un tampon avec : + 71 c4 80 df 93 d6 ae 2f 1e fa d1 44 7c 66 c9 52 5e 31 62 18 cf 51 fc 8d 9e d8 32 f2 da f1 8b 73 */ +---- + +[NOTE] +Cette fonction n'est pas disponible dans l'API script. + ==== crypto_hash_pbkdf2 _WeeChat ≥ 2.8._ diff --git a/doc/it/weechat_plugin_api.it.adoc b/doc/it/weechat_plugin_api.it.adoc index c0d0d81c6..26cdf1144 100644 --- a/doc/it/weechat_plugin_api.it.adoc +++ b/doc/it/weechat_plugin_api.it.adoc @@ -3895,6 +3895,50 @@ rc = weechat_crypto_hash (data, strlen (data), "sha256", hash, &hash_size); Questa funzione non è disponibile nelle API per lo scripting. // TRANSLATION MISSING +==== crypto_hash_file + +_WeeChat ≥ 3.7._ + +Compute hash of a file. + +Prototipo: + +[source,c] +---- +int weechat_crypto_hash_file (const char *filename, const char *hash_algo, + void *hash, int *hash_size); +---- + +Argomenti: + +* _filename_: percorso e nome file +* _hash_algo_: the hash algorithm, see table in function + <<crypto_hash_algorithms,crypto_hash>> +* _hash_: pointer to the hash variable, which is used to store the resulting hash + (the buffer must be large enough, according to the algorithm, see table in + function <<crypto_hash_algorithms,crypto_hash>>) +* _hash_size_: pointer to a variable used to store the length of the hash computed + (in bytes) (can be NULL) + +Valore restituito: + +* 1 if OK, 0 if error + +Esempio in C: + +[source,c] +---- +char hash[256 / 8]; +int rc, hash_size; +rc = weechat_crypto_hash_file ("/path/to/file", "sha256", hash, &hash_size); +/* rc == 1, hash_size == 32 and hash is a buffer with: + 71 c4 80 df 93 d6 ae 2f 1e fa d1 44 7c 66 c9 52 5e 31 62 18 cf 51 fc 8d 9e d8 32 f2 da f1 8b 73 */ +---- + +[NOTE] +Questa funzione non è disponibile nelle API per lo scripting. + +// TRANSLATION MISSING ==== crypto_hash_pbkdf2 _WeeChat ≥ 2.8._ diff --git a/doc/ja/weechat_plugin_api.ja.adoc b/doc/ja/weechat_plugin_api.ja.adoc index fd075655a..bacac2347 100644 --- a/doc/ja/weechat_plugin_api.ja.adoc +++ b/doc/ja/weechat_plugin_api.ja.adoc @@ -3815,6 +3815,50 @@ rc = weechat_crypto_hash (data, strlen (data), "sha256", hash, &hash_size); [NOTE] スクリプト API ではこの関数を利用できません。 +// TRANSLATION MISSING +==== crypto_hash_flie + +_WeeChat バージョン 3.7 以上で利用可。_ + +Compute hash of a file. + +プロトタイプ: + +[source,c] +---- +int weechat_crypto_hash_file (const char *filename, const char *hash_algo, + void *hash, int *hash_size); +---- + +引数: + +* _filename_: パスやファイル名 +* _hash_algo_: the hash algorithm, see table in function + <<crypto_hash_algorithms,crypto_hash>> +* _hash_: pointer to the hash variable, which is used to store the resulting hash + (the buffer must be large enough, according to the algorithm, see table in + function <<crypto_hash_algorithms,crypto_hash>>) +* _hash_size_: pointer to a variable used to store the size of the hash computed + (in bytes) (can be NULL) + +戻り値: + +* 成功した場合は 1、失敗した場合は 0 + +C 言語での使用例: + +[source,c] +---- +char hash[256 / 8]; +int rc, hash_size; +rc = weechat_crypto_hash_file ("/path/to/file", "sha256", hash, &hash_size); +/* rc == 1, hash_size == 32 and hash is a buffer with: + 71 c4 80 df 93 d6 ae 2f 1e fa d1 44 7c 66 c9 52 5e 31 62 18 cf 51 fc 8d 9e d8 32 f2 da f1 8b 73 */ +---- + +[NOTE] +スクリプト API ではこの関数を利用できません。 + ==== crypto_hash_pbkdf2 _WeeChat バージョン 2.8 以上で利用可。_ diff --git a/doc/sr/weechat_plugin_api.sr.adoc b/doc/sr/weechat_plugin_api.sr.adoc index 61d87977c..205ea6e42 100644 --- a/doc/sr/weechat_plugin_api.sr.adoc +++ b/doc/sr/weechat_plugin_api.sr.adoc @@ -3624,6 +3624,52 @@ rc = weechat_crypto_hash (data, strlen (data), "sha256", hash, &hash_size); [NOTE] Ова функција није доступна у API скриптовања. +==== crypto_hash_file + +_WeeChat ≥ 3.7._ + +// TRANSLATION MISSING +Compute hash of a file. + +Прототип: + +[source,c] +---- +int weechat_crypto_hash_file (const char *filename, const char *hash_algo, + void *hash, int *hash_size); +---- + +Аргументи: + +* _filename_: путања и име фајла +// TRANSLATION MISSING +* _hash_algo_: the hash algorithm, see table in function + <<crypto_hash_algorithms,crypto_hash>> +// TRANSLATION MISSING +* _hash_: pointer to the hash variable, which is used to store the resulting hash + (the buffer must be large enough, according to the algorithm, see table in + function <<crypto_hash_algorithms,crypto_hash>>) +* _hash_size_: показивач на променљиву која се користи за чување величине израчунатог хеша (у бајтовима) (може да буде NULL) + +Повратна вредност: + +* 1 ако је све OK, 0 у случају грешке + +C пример: + +// TRANSLATION MISSING +[source,c] +---- +char hash[256 / 8]; +int rc, hash_size; +rc = weechat_crypto_hash_file ("/path/to/file", "sha256", hash, &hash_size); +/* rc == 1, hash_size == 32 и хеш је бафер са: + 71 c4 80 df 93 d6 ae 2f 1e fa d1 44 7c 66 c9 52 5e 31 62 18 cf 51 fc 8d 9e d8 32 f2 da f1 8b 73 */ +---- + +[NOTE] +Ова функција није доступна у API скриптовања. + ==== crypto_hash_pbkdf2 _WeeChat ≥ 2.8._ diff --git a/src/core/wee-crypto.c b/src/core/wee-crypto.c index 00ee3292c..f99d7aac0 100644 --- a/src/core/wee-crypto.c +++ b/src/core/wee-crypto.c @@ -26,6 +26,7 @@ #include <stdlib.h> #include <stdio.h> #include <stdint.h> +#include <sys/stat.h> #include <time.h> #include <math.h> #include <gcrypt.h> @@ -160,6 +161,105 @@ hash_end: } /* + * Computes hash of file using the given hash algorithm. + * + * The hash size depends on the algorithm, common ones are: + * + * GCRY_MD_CRC32 32 bits == 4 bytes + * GCRY_MD_MD5 128 bits == 16 bytes + * GCRY_MD_SHA1 160 bits == 20 bytes + * GCRY_MD_SHA224 224 bits == 28 bytes + * GCRY_MD_SHA256 256 bits == 32 bytes + * GCRY_MD_SHA384 384 bits == 48 bytes + * GCRY_MD_SHA512 512 bits == 64 bytes + * GCRY_MD_SHA3_224 224 bits == 28 bytes (libgcrypt ≥ 1.7.0) + * GCRY_MD_SHA3_256 256 bits == 32 bytes (libgcrypt ≥ 1.7.0) + * GCRY_MD_SHA3_384 384 bits == 48 bytes (libgcrypt ≥ 1.7.0) + * GCRY_MD_SHA3_512 512 bits == 64 bytes (libgcrypt ≥ 1.7.0) + * + * The result hash is stored in "hash" (the buffer must be large enough). + * + * If hash_size is not NULL, the length of hash is stored in *hash_size + * (in bytes). + * + * Returns: + * 1: OK + * 0: error + */ + +int +weecrypto_hash_file (const char *filename, int hash_algo, + void *hash, int *hash_size) +{ + gcry_md_hd_t *hd_md; + struct stat st; + FILE *file; + size_t num_read; + int rc, hd_md_opened, algo_size; + unsigned char *ptr_hash; + char buffer[4096]; + + rc = 0; + hd_md = NULL; + hd_md_opened = 0; + file = NULL; + + if (!hash) + goto hash_end; + + if (hash_size) + *hash_size = 0; + + if (!filename || !filename[0] || !hash) + goto hash_end; + + if (stat (filename, &st) == -1) + goto hash_end; + + file = fopen (filename, "r"); + if (!file) + goto hash_end; + + hd_md = malloc (sizeof (gcry_md_hd_t)); + if (!hd_md) + goto hash_end; + + if (gcry_md_open (hd_md, hash_algo, 0) != 0) + goto hash_end; + + hd_md_opened = 1; + + while (!feof (file)) + { + num_read = fread (buffer, 1, sizeof (buffer), file); + if (num_read == 0) + break; + gcry_md_write (*hd_md, buffer, num_read); + } + + ptr_hash = gcry_md_read (*hd_md, hash_algo); + if (!ptr_hash) + goto hash_end; + + algo_size = gcry_md_get_algo_dlen (hash_algo); + memcpy (hash, ptr_hash, algo_size); + if (hash_size) + *hash_size = algo_size; + + rc = 1; + +hash_end: + if (hd_md) + { + if (hd_md_opened) + gcry_md_close (*hd_md); + free (hd_md); + } + if (file) + fclose (file); + return rc; +} +/* * Computes PKCS#5 Passphrase Based Key Derivation Function number 2 (PBKDF2) * hash of data. * diff --git a/src/core/wee-crypto.h b/src/core/wee-crypto.h index fd7675b9e..863bccb23 100644 --- a/src/core/wee-crypto.h +++ b/src/core/wee-crypto.h @@ -26,6 +26,8 @@ extern int weecrypto_get_hash_algo (const char *hash_algo); extern int weecrypto_hash (const void *data, int data_size, int hash_algo, void *hash, int *hash_size); +extern int weecrypto_hash_file (const char *filename, int hash_algo, + void *hash, int *hash_size); extern int weecrypto_hash_pbkdf2 (const void *data, int data_size, int hash_algo, const void *salt, int salt_size, diff --git a/src/plugins/plugin-api.c b/src/plugins/plugin-api.c index 3ae8a6332..d4a374899 100644 --- a/src/plugins/plugin-api.c +++ b/src/plugins/plugin-api.c @@ -128,6 +128,36 @@ plugin_api_crypto_hash (const void *data, int data_size, const char *hash_algo, } /* + * Computes hash of a file using the given algorithm. + * + * Returns: + * 1: OK + * 0: error + */ + +int +plugin_api_crypto_hash_file (const char *filename, const char *hash_algo, + void *hash, int *hash_size) +{ + int algo; + + if (!hash) + return 0; + + if (hash_size) + *hash_size = 0; + + if (!filename || !filename[0] || !hash_algo) + return 0; + + algo = weecrypto_get_hash_algo (hash_algo); + if (algo == GCRY_MD_NONE) + return 0; + + return weecrypto_hash_file (filename, algo, hash, hash_size); +} + +/* * Computes PKCS#5 Passphrase Based Key Derivation Function number 2 (PBKDF2) * hash of data. * diff --git a/src/plugins/plugin-api.h b/src/plugins/plugin-api.h index 4eed26145..6cc6f1646 100644 --- a/src/plugins/plugin-api.h +++ b/src/plugins/plugin-api.h @@ -33,6 +33,9 @@ extern const char *plugin_api_ngettext (const char *single, const char *plural, extern int plugin_api_crypto_hash (const void *data, int data_size, const char *hash_algo, void *hash, int *hash_size); +extern int plugin_api_crypto_hash_file (const char *filename, + const char *hash_algo, + void *hash, int *hash_size); extern int plugin_api_crypto_hash_pbkdf2 (const void *data, int data_size, const char *hash_algo, const void *salt, int salt_size, diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 7f8e2b424..42a940656 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -665,6 +665,7 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv) new_plugin->utf8_strndup = &utf8_strndup; new_plugin->crypto_hash = &plugin_api_crypto_hash; + new_plugin->crypto_hash_file = &plugin_api_crypto_hash_file; new_plugin->crypto_hash_pbkdf2 = &plugin_api_crypto_hash_pbkdf2; new_plugin->crypto_hmac = &plugin_api_crypto_hmac; diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h index 43e04964c..bd0595591 100644 --- a/src/plugins/weechat-plugin.h +++ b/src/plugins/weechat-plugin.h @@ -68,7 +68,7 @@ struct timeval; * please change the date with current one; for a second change at same * date, increment the 01, otherwise please keep 01. */ -#define WEECHAT_PLUGIN_API_VERSION "20220720-02" +#define WEECHAT_PLUGIN_API_VERSION "20220816-01" /* macros for defining plugin infos */ #define WEECHAT_PLUGIN_NAME(__name) \ @@ -380,6 +380,8 @@ struct t_weechat_plugin /* crypto */ int (*crypto_hash) (const void *data, int data_size, const char *hash_algo, void *hash, int *hash_size); + int (*crypto_hash_file) (const char *fliename, + const char *hash_algo, void *hash, int *hash_size); int (*crypto_hash_pbkdf2) (const void *data, int data_size, const char *hash_algo, const void *salt, int salt_size, @@ -1372,6 +1374,10 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); __hash, __hash_size) \ (weechat_plugin->crypto_hash)(__data, __data_size, __hash_algo, \ __hash, __hash_size) +#define weechat_crypto_hash_file(__filename, __hash_algo, __hash, \ + __hash_size) \ + (weechat_plugin->crypto_hash_file)(__filename, __hash_algo, __hash, \ + __hash_size) #define weechat_crypto_hash_pbkdf2(__data, __data_size, __hash_algo, \ __salt, __salt_size, __iterations, \ __hash, __hash_size) \ diff --git a/tests/unit/core/test-core-crypto.cpp b/tests/unit/core/test-core-crypto.cpp index acda37669..4f7833ec6 100644 --- a/tests/unit/core/test-core-crypto.cpp +++ b/tests/unit/core/test-core-crypto.cpp @@ -23,6 +23,8 @@ extern "C" { +#include <unistd.h> +#include <stdio.h> #include <string.h> #include <ctype.h> #include <gcrypt.h> @@ -111,6 +113,27 @@ extern "C" } \ LONGS_EQUAL(hash_size_expected, hash_size); +#define WEE_CHECK_HASH_FILE(__result_code, __result_hash, \ + __filename, __hash_algo) \ + if (__result_hash) \ + { \ + hash_size_expected = string_base16_decode (__result_hash, \ + hash_expected); \ + } \ + else \ + { \ + hash_size_expected = 0; \ + } \ + hash_size = -1; \ + LONGS_EQUAL(__result_code, \ + weecrypto_hash_file (__filename, __hash_algo, \ + hash, &hash_size)); \ + if (__result_hash) \ + { \ + MEMCMP_EQUAL(hash_expected, hash, hash_size); \ + } \ + LONGS_EQUAL(hash_size_expected, hash_size); + #define WEE_CHECK_HASH_PBKDF2(__result_code, __result_hash, \ __data, __data_size, \ __hash_algo, __salt, __salt_size, \ @@ -223,8 +246,8 @@ TEST(CoreCrypto, Hash) data_size = strlen (data); - WEE_CHECK_HASH(0, NULL, NULL, 0, 0); - WEE_CHECK_HASH(0, NULL, "test", 0, 0); + WEE_CHECK_HASH(0, NULL, NULL, 0, GCRY_MD_SHA256); + WEE_CHECK_HASH(0, NULL, "test", 0, GCRY_MD_SHA256); LONGS_EQUAL (0, weecrypto_hash (data, data_size, GCRY_MD_SHA256, NULL, NULL)); @@ -246,6 +269,48 @@ TEST(CoreCrypto, Hash) /* * Tests functions: + * weecrypto_hash_file + */ + +TEST(CoreCrypto, HashFile) +{ + const char *data = DATA_HASH_MSG; + char *filename, hash_expected[4096], hash[4096]; + FILE *file; + int hash_size_expected, hash_size; + + filename = string_eval_path_home ("${weechat_data_dir}/test_file.txt", + NULL, NULL, NULL); + file = fopen (filename, "w"); + fwrite (data, 1, strlen (data), file); + fflush (file); + fclose (file); + + WEE_CHECK_HASH_FILE(0, NULL, NULL, GCRY_MD_SHA256); + + LONGS_EQUAL (0, weecrypto_hash_file (filename, GCRY_MD_SHA256, + NULL, NULL)); + + WEE_CHECK_HASH_FILE(1, DATA_HASH_CRC32, filename, GCRY_MD_CRC32); + WEE_CHECK_HASH_FILE(1, DATA_HASH_MD5, filename, GCRY_MD_MD5); + WEE_CHECK_HASH_FILE(1, DATA_HASH_SHA1, filename, GCRY_MD_SHA1); + WEE_CHECK_HASH_FILE(1, DATA_HASH_SHA224, filename, GCRY_MD_SHA224); + WEE_CHECK_HASH_FILE(1, DATA_HASH_SHA256, filename, GCRY_MD_SHA256); + WEE_CHECK_HASH_FILE(1, DATA_HASH_SHA384, filename, GCRY_MD_SHA384); + WEE_CHECK_HASH_FILE(1, DATA_HASH_SHA512, filename, GCRY_MD_SHA512); +#if GCRYPT_VERSION_NUMBER >= 0x010700 + WEE_CHECK_HASH_FILE(1, DATA_HASH_SHA3_224, filename, GCRY_MD_SHA3_224); + WEE_CHECK_HASH_FILE(1, DATA_HASH_SHA3_256, filename, GCRY_MD_SHA3_256); + WEE_CHECK_HASH_FILE(1, DATA_HASH_SHA3_384, filename, GCRY_MD_SHA3_384); + WEE_CHECK_HASH_FILE(1, DATA_HASH_SHA3_512, filename, GCRY_MD_SHA3_512); +#endif + + unlink (filename); + free (filename); +} + +/* + * Tests functions: * weecrypto_hash_pbkdf2 */ |