core: move crypto functions to wee-crypto.c, rename API function string_hash to crypto_hash
parent
c4ef3d6c2e
commit
9a6a27ef58
|
@ -22,7 +22,7 @@ New features::
|
|||
|
||||
* core: add variable "old_full_name" in buffer, set during buffer renaming (issue #1428)
|
||||
* core: add debug option "-d" in command /eval (issue #1434)
|
||||
* api: add function string_hash
|
||||
* api: add function crypto_hash
|
||||
* api: add info "weechat_headless" (issue #1433)
|
||||
* buflist: add pointer "window" in bar item evaluation
|
||||
* relay: reject client with weechat protocol if password or totp is received in init command but not set in WeeChat (issue #1435)
|
||||
|
|
|
@ -125,6 +125,7 @@ WeeChat "core" is located in following directories:
|
|||
| wee-completion.c | Default completions.
|
||||
| wee-config-file.c | Configuration file management.
|
||||
| wee-config.c | Configuration options for WeeChat core (file weechat.conf).
|
||||
| wee-crypto.c | Cryptographic functions.
|
||||
| wee-debug.c | Some debug functions.
|
||||
| wee-eval.c | Evaluation of expressions with references to internal vars.
|
||||
| wee-hashtable.c | Hashtables.
|
||||
|
@ -391,6 +392,7 @@ WeeChat "core" is located in following directories:
|
|||
| core/ | Root of unit tests for core.
|
||||
| test-core-arraylist.cpp | Tests: arraylists.
|
||||
| test-core-calc.cpp | Tests: calculation of expressions.
|
||||
| test-core-crypto.cpp | Tests: cryptographic functions.
|
||||
| test-core-eval.cpp | Tests: evaluation of expressions.
|
||||
| test-core-hashtble.cpp | Tests: hashtables.
|
||||
| test-core-hdata.cpp | Tests: hdata.
|
||||
|
|
|
@ -2061,66 +2061,6 @@ char *dump = weechat_string_hex_dump (string, strlen (string), 8, " >> ", NULL);
|
|||
[NOTE]
|
||||
This function is not available in scripting API.
|
||||
|
||||
==== string_hash
|
||||
|
||||
_WeeChat ≥ 2.8._
|
||||
|
||||
Compute hash of data.
|
||||
|
||||
Prototype:
|
||||
|
||||
[source,C]
|
||||
----
|
||||
int string_hash (const void *data, int data_size, const char *hash_algo, void *hash, int *hash_size);
|
||||
----
|
||||
|
||||
Arguments:
|
||||
|
||||
* _data_: the data to hash
|
||||
* _data_size_: number of bytes to hash in _data_
|
||||
* _hash_algo_: the hash algorithm, see table below
|
||||
* _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 below)
|
||||
* _hash_size_: pointer to a variable used to store the size of the hash computed
|
||||
(in bytes) (can be NULL)
|
||||
|
||||
Supported hash algorithms:
|
||||
|
||||
[width="100%",cols="2,2,3,6",options="header"]
|
||||
|===
|
||||
| Value | Algorithm | Hash size | Notes
|
||||
| `+crc32+` | CRC32 | 4 bytes (32 bits) | Not a hash algorithm in the cryptographic sense.
|
||||
| `+md5+` | MD5 | 16 bytes (128 bits) | *Weak*, not recommended for cryptography usage.
|
||||
| `+sha1+` | SHA-1 | 20 bytes (160 bits) | *Weak*, not recommended for cryptography usage.
|
||||
| `+sha224+` | SHA-224 | 28 bytes (224 bits) |
|
||||
| `+sha256+` | SHA-256 | 32 bytes (256 bits) |
|
||||
| `+sha384+` | SHA-384 | 48 bytes (384 bits) |
|
||||
| `+sha512+` | SHA-512 | 64 bytes (512 bits) |
|
||||
| `+sha3-224+` | SHA3-224 | 28 bytes (224 bits) |
|
||||
| `+sha3-256+` | SHA3-256 | 32 bytes (256 bits) |
|
||||
| `+sha3-384+` | SHA3-384 | 48 bytes (384 bits) |
|
||||
| `+sha3-512+` | SHA3-512 | 64 bytes (512 bits) |
|
||||
|===
|
||||
|
||||
Return value:
|
||||
|
||||
* 1 if OK, 0 if error
|
||||
|
||||
C example:
|
||||
|
||||
[source,C]
|
||||
----
|
||||
const char *data = "abcdefghijklmnopqrstuvwxyz";
|
||||
char hash[256 / 8];
|
||||
int rc, hash_size;
|
||||
rc = weechat_string_hash (data, strlen (data), "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.
|
||||
|
||||
==== string_is_command_char
|
||||
|
||||
_WeeChat ≥ 0.3.2._
|
||||
|
@ -3386,6 +3326,72 @@ free (string);
|
|||
[NOTE]
|
||||
This function is not available in scripting API.
|
||||
|
||||
[[crypto]]
|
||||
=== Cryptography
|
||||
|
||||
Some cryptographic functions.
|
||||
|
||||
==== crypto_hash
|
||||
|
||||
_WeeChat ≥ 2.8._
|
||||
|
||||
Compute hash of data.
|
||||
|
||||
Prototype:
|
||||
|
||||
[source,C]
|
||||
----
|
||||
int weechat_crypto_hash (const void *data, int data_size, const char *hash_algo,
|
||||
void *hash, int *hash_size);
|
||||
----
|
||||
|
||||
Arguments:
|
||||
|
||||
* _data_: the data to hash
|
||||
* _data_size_: number of bytes to hash in _data_
|
||||
* _hash_algo_: the hash algorithm, see table below
|
||||
* _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 below)
|
||||
* _hash_size_: pointer to a variable used to store the size of the hash computed
|
||||
(in bytes) (can be NULL)
|
||||
|
||||
Supported hash algorithms:
|
||||
|
||||
[width="100%",cols="2,2,3,6",options="header"]
|
||||
|===
|
||||
| Value | Algorithm | Hash size | Notes
|
||||
| `+crc32+` | CRC32 | 4 bytes (32 bits) | Not a hash algorithm in the cryptographic sense.
|
||||
| `+md5+` | MD5 | 16 bytes (128 bits) | *Weak*, not recommended for cryptography usage.
|
||||
| `+sha1+` | SHA-1 | 20 bytes (160 bits) | *Weak*, not recommended for cryptography usage.
|
||||
| `+sha224+` | SHA-224 | 28 bytes (224 bits) |
|
||||
| `+sha256+` | SHA-256 | 32 bytes (256 bits) |
|
||||
| `+sha384+` | SHA-384 | 48 bytes (384 bits) |
|
||||
| `+sha512+` | SHA-512 | 64 bytes (512 bits) |
|
||||
| `+sha3-224+` | SHA3-224 | 28 bytes (224 bits) |
|
||||
| `+sha3-256+` | SHA3-256 | 32 bytes (256 bits) |
|
||||
| `+sha3-384+` | SHA3-384 | 48 bytes (384 bits) |
|
||||
| `+sha3-512+` | SHA3-512 | 64 bytes (512 bits) |
|
||||
|===
|
||||
|
||||
Return value:
|
||||
|
||||
* 1 if OK, 0 if error
|
||||
|
||||
C example:
|
||||
|
||||
[source,C]
|
||||
----
|
||||
const char *data = "abcdefghijklmnopqrstuvwxyz";
|
||||
char hash[256 / 8];
|
||||
int rc, hash_size;
|
||||
rc = weechat_crypto_hash (data, strlen (data), "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.
|
||||
|
||||
[[directories]]
|
||||
=== Directories
|
||||
|
||||
|
|
|
@ -127,6 +127,7 @@ Le cœur de WeeChat est situé dans les répertoires suivants :
|
|||
| wee-completion.c | Complétions par défaut.
|
||||
| wee-config-file.c | Gestion des fichiers de configuration.
|
||||
| wee-config.c | Options de configuration du cœur de WeeChat (fichier weechat.conf).
|
||||
| wee-crypto.c | Fonctions de cryptographie.
|
||||
| wee-debug.c | Quelques fonctions de debug.
|
||||
| wee-eval.c | Évaluation d'expressions avec des références à des variables internes.
|
||||
| wee-hashtable.c | Tables de hachage.
|
||||
|
@ -393,6 +394,7 @@ Le cœur de WeeChat est situé dans les répertoires suivants :
|
|||
| core/ | Racine des tests unitaires pour le cœur.
|
||||
| test-core-arraylist.cpp | Tests : listes avec tableau (« arraylists »).
|
||||
| test-core-calc.cpp | Tests : calcul d'expressions.
|
||||
| test-core-crypto.cpp | Tests : fonctions cryptographiques.
|
||||
| test-core-eval.cpp | Tests : évaluation d'expressions.
|
||||
| test-core-hashtble.cpp | Tests : tables de hachage.
|
||||
| test-core-hdata.cpp | Tests : hdata.
|
||||
|
|
|
@ -2099,67 +2099,6 @@ char *dump = weechat_string_hex_dump (string, strlen (string), 8, " >> ", NULL);
|
|||
[NOTE]
|
||||
Cette fonction n'est pas disponible dans l'API script.
|
||||
|
||||
==== string_hash
|
||||
|
||||
_WeeChat ≥ 2.8._
|
||||
|
||||
Calculer le hachage des données.
|
||||
|
||||
Prototype :
|
||||
|
||||
[source,C]
|
||||
----
|
||||
int string_hash (const void *data, int data_size, const char *hash_algo, void *hash, int *hash_size);
|
||||
----
|
||||
|
||||
Paramètres :
|
||||
|
||||
* _data_ : les données à hacher
|
||||
* _data_size_ : nombre d'octets à hacher dans _data_
|
||||
* _hash_algo_ : l'algorithme de hachage, voir le tableau ci-dessous
|
||||
* _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 ci-dessous)
|
||||
* _hash_size_ : pointeur vers une variable utiliser pour stocker la longueur
|
||||
du résultat du hachage (en octets) (peut être NULL)
|
||||
|
||||
Algorithmes de hachage supportés :
|
||||
|
||||
[width="100%",cols="2,2,3,6",options="header"]
|
||||
|===
|
||||
| Valeur | Algorithme | Taille du haché | Notes
|
||||
| `+crc32+` | CRC32 | 4 octets (32 bits) | Pas un algorithme de hachage au sens cryptographique.
|
||||
| `+md5+` | MD5 | 16 octets (128 bits) | *Faible*, non recommandé pour un usage cryptographique.
|
||||
| `+sha1+` | SHA-1 | 20 octets (160 bits) | *Faible*, non recommandé pour un usage cryptographique.
|
||||
| `+sha224+` | SHA-224 | 28 octets (224 bits) |
|
||||
| `+sha256+` | SHA-256 | 32 octets (256 bits) |
|
||||
| `+sha384+` | SHA-384 | 48 octets (384 bits) |
|
||||
| `+sha512+` | SHA-512 | 64 octets (512 bits) |
|
||||
| `+sha3-224+` | SHA3-224 | 28 octets (224 bits) |
|
||||
| `+sha3-256+` | SHA3-256 | 32 octets (256 bits) |
|
||||
| `+sha3-384+` | SHA3-384 | 48 octets (384 bits) |
|
||||
| `+sha3-512+` | SHA3-512 | 64 octets (512 bits) |
|
||||
|===
|
||||
|
||||
Valeur de retour :
|
||||
|
||||
* 1 si OK, 0 si erreur
|
||||
|
||||
Exemple en C :
|
||||
|
||||
[source,C]
|
||||
----
|
||||
const char *data = "abcdefghijklmnopqrstuvwxyz";
|
||||
char hash[256 / 8];
|
||||
int rc, hash_size;
|
||||
rc = weechat_string_hash (data, strlen (data), "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.
|
||||
|
||||
==== string_is_command_char
|
||||
|
||||
_WeeChat ≥ 0.3.2._
|
||||
|
@ -3446,6 +3385,73 @@ free (str);
|
|||
[NOTE]
|
||||
Cette fonction n'est pas disponible dans l'API script.
|
||||
|
||||
[[crypto]]
|
||||
=== Cryptographie
|
||||
|
||||
Fonctions de cryptographie.
|
||||
|
||||
==== crypto_hash
|
||||
|
||||
_WeeChat ≥ 2.8._
|
||||
|
||||
Calculer le hachage des données.
|
||||
|
||||
Prototype :
|
||||
|
||||
[source,C]
|
||||
----
|
||||
int weechat_crypto_hash (const void *data, int data_size, const char *hash_algo,
|
||||
void *hash, int *hash_size);
|
||||
----
|
||||
|
||||
Paramètres :
|
||||
|
||||
* _data_ : les données à hacher
|
||||
* _data_size_ : nombre d'octets à hacher dans _data_
|
||||
* _hash_algo_ : l'algorithme de hachage, voir le tableau ci-dessous
|
||||
* _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 ci-dessous)
|
||||
* _hash_size_ : pointeur vers une variable utiliser pour stocker la longueur
|
||||
du résultat du hachage (en octets) (peut être NULL)
|
||||
|
||||
Algorithmes de hachage supportés :
|
||||
|
||||
[width="100%",cols="2,2,3,6",options="header"]
|
||||
|===
|
||||
| Valeur | Algorithme | Taille du haché | Notes
|
||||
| `+crc32+` | CRC32 | 4 octets (32 bits) | Pas un algorithme de hachage au sens cryptographique.
|
||||
| `+md5+` | MD5 | 16 octets (128 bits) | *Faible*, non recommandé pour un usage cryptographique.
|
||||
| `+sha1+` | SHA-1 | 20 octets (160 bits) | *Faible*, non recommandé pour un usage cryptographique.
|
||||
| `+sha224+` | SHA-224 | 28 octets (224 bits) |
|
||||
| `+sha256+` | SHA-256 | 32 octets (256 bits) |
|
||||
| `+sha384+` | SHA-384 | 48 octets (384 bits) |
|
||||
| `+sha512+` | SHA-512 | 64 octets (512 bits) |
|
||||
| `+sha3-224+` | SHA3-224 | 28 octets (224 bits) |
|
||||
| `+sha3-256+` | SHA3-256 | 32 octets (256 bits) |
|
||||
| `+sha3-384+` | SHA3-384 | 48 octets (384 bits) |
|
||||
| `+sha3-512+` | SHA3-512 | 64 octets (512 bits) |
|
||||
|===
|
||||
|
||||
Valeur de retour :
|
||||
|
||||
* 1 si OK, 0 si erreur
|
||||
|
||||
Exemple en C :
|
||||
|
||||
[source,C]
|
||||
----
|
||||
const char *data = "abcdefghijklmnopqrstuvwxyz";
|
||||
char hash[256 / 8];
|
||||
int rc, hash_size;
|
||||
rc = weechat_crypto_hash (data, strlen (data), "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.
|
||||
|
||||
[[directories]]
|
||||
=== Répertoires
|
||||
|
||||
|
|
|
@ -2152,68 +2152,6 @@ char *dump = weechat_string_hex_dump (string, strlen (string), 8, " >> ", NULL);
|
|||
[NOTE]
|
||||
Questa funzione non è disponibile nelle API per lo scripting.
|
||||
|
||||
// TRANSLATION MISSING
|
||||
==== string_hash
|
||||
|
||||
_WeeChat ≥ 2.8._
|
||||
|
||||
Compute hash of data.
|
||||
|
||||
Prototipo:
|
||||
|
||||
[source,C]
|
||||
----
|
||||
int string_hash (const void *data, int data_size, const char *hash_algo, void *hash, int *hash_size);
|
||||
----
|
||||
|
||||
Argomenti:
|
||||
|
||||
* _data_: the data to hash
|
||||
* _data_size_: number of bytes to hash in _data_
|
||||
* _hash_algo_: the hash algorithm, see table below
|
||||
* _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 below)
|
||||
* _hash_size_: pointer to a variable used to store the length of the hash computed
|
||||
(in bytes) (can be NULL)
|
||||
|
||||
Supported hash algorithms:
|
||||
|
||||
[width="100%",cols="2,2,3,6",options="header"]
|
||||
|===
|
||||
| Value | Algorithm | Hash size | Notes
|
||||
| `+crc32+` | CRC32 | 4 bytes (32 bits) | Not a hash algorithm in the cryptographic sense.
|
||||
| `+md5+` | MD5 | 16 bytes (128 bits) | *Weak*, not recommended for cryptography usage.
|
||||
| `+sha1+` | SHA-1 | 20 bytes (160 bits) | *Weak*, not recommended for cryptography usage.
|
||||
| `+sha224+` | SHA-224 | 28 bytes (224 bits) |
|
||||
| `+sha256+` | SHA-256 | 32 bytes (256 bits) |
|
||||
| `+sha384+` | SHA-384 | 48 bytes (384 bits) |
|
||||
| `+sha512+` | SHA-512 | 64 bytes (512 bits) |
|
||||
| `+sha3-224+` | SHA3-224 | 28 bytes (224 bits) |
|
||||
| `+sha3-256+` | SHA3-256 | 32 bytes (256 bits) |
|
||||
| `+sha3-384+` | SHA3-384 | 48 bytes (384 bits) |
|
||||
| `+sha3-512+` | SHA3-512 | 64 bytes (512 bits) |
|
||||
|===
|
||||
|
||||
Valore restituito:
|
||||
|
||||
// TRANSLATION MISSING
|
||||
* 1 if OK, 0 if error
|
||||
|
||||
Esempio in C:
|
||||
|
||||
[source,C]
|
||||
----
|
||||
const char *data = "abcdefghijklmnopqrstuvwxyz";
|
||||
char hash[256 / 8];
|
||||
int rc, hash_size;
|
||||
rc = weechat_string_hash (data, strlen (data), "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.
|
||||
|
||||
==== string_is_command_char
|
||||
|
||||
_WeeChat ≥ 0.3.2._
|
||||
|
@ -3528,6 +3466,75 @@ free (string);
|
|||
[NOTE]
|
||||
Questa funzione non è disponibile nelle API per lo scripting.
|
||||
|
||||
// TRANSLATION MISSING
|
||||
[[crypto]]
|
||||
=== Cryptography
|
||||
|
||||
Some cryptographic functions.
|
||||
|
||||
// TRANSLATION MISSING
|
||||
==== crypto_hash
|
||||
|
||||
_WeeChat ≥ 2.8._
|
||||
|
||||
Compute hash of data.
|
||||
|
||||
Prototipo:
|
||||
|
||||
[source,C]
|
||||
----
|
||||
int weechat_crypto_hash (const void *data, int data_size, const char *hash_algo,
|
||||
void *hash, int *hash_size);
|
||||
----
|
||||
|
||||
Argomenti:
|
||||
|
||||
* _data_: the data to hash
|
||||
* _data_size_: number of bytes to hash in _data_
|
||||
* _hash_algo_: the hash algorithm, see table below
|
||||
* _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 below)
|
||||
* _hash_size_: pointer to a variable used to store the length of the hash computed
|
||||
(in bytes) (can be NULL)
|
||||
|
||||
Supported hash algorithms:
|
||||
|
||||
[width="100%",cols="2,2,3,6",options="header"]
|
||||
|===
|
||||
| Value | Algorithm | Hash size | Notes
|
||||
| `+crc32+` | CRC32 | 4 bytes (32 bits) | Not a hash algorithm in the cryptographic sense.
|
||||
| `+md5+` | MD5 | 16 bytes (128 bits) | *Weak*, not recommended for cryptography usage.
|
||||
| `+sha1+` | SHA-1 | 20 bytes (160 bits) | *Weak*, not recommended for cryptography usage.
|
||||
| `+sha224+` | SHA-224 | 28 bytes (224 bits) |
|
||||
| `+sha256+` | SHA-256 | 32 bytes (256 bits) |
|
||||
| `+sha384+` | SHA-384 | 48 bytes (384 bits) |
|
||||
| `+sha512+` | SHA-512 | 64 bytes (512 bits) |
|
||||
| `+sha3-224+` | SHA3-224 | 28 bytes (224 bits) |
|
||||
| `+sha3-256+` | SHA3-256 | 32 bytes (256 bits) |
|
||||
| `+sha3-384+` | SHA3-384 | 48 bytes (384 bits) |
|
||||
| `+sha3-512+` | SHA3-512 | 64 bytes (512 bits) |
|
||||
|===
|
||||
|
||||
Valore restituito:
|
||||
|
||||
// TRANSLATION MISSING
|
||||
* 1 if OK, 0 if error
|
||||
|
||||
Esempio in C:
|
||||
|
||||
[source,C]
|
||||
----
|
||||
const char *data = "abcdefghijklmnopqrstuvwxyz";
|
||||
char hash[256 / 8];
|
||||
int rc, hash_size;
|
||||
rc = weechat_crypto_hash (data, strlen (data), "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.
|
||||
|
||||
[[directories]]
|
||||
=== Cartelle
|
||||
|
||||
|
|
|
@ -132,6 +132,8 @@ WeeChat "core" は以下のディレクトリに配置されています:
|
|||
| wee-completion.c | デフォルト補完
|
||||
| wee-config-file.c | 設定ファイル管理
|
||||
| wee-config.c | WeeChat コアの設定オプション (weechat.conf ファイル)
|
||||
// TRANSLATION MISSING
|
||||
| wee-crypto.c | Cryptographic functions.
|
||||
| wee-debug.c | デバッグ用関数
|
||||
| wee-eval.c | 内部変数へのリファレンスを含む式を評価
|
||||
| wee-hashtable.c | ハッシュテーブル
|
||||
|
@ -400,6 +402,8 @@ WeeChat "core" は以下のディレクトリに配置されています:
|
|||
| test-core-arraylist.cpp | テスト: 配列リスト
|
||||
// TRANSLATION MISSING
|
||||
| test-core-calc.cpp | Tests: calculation of expressions.
|
||||
// TRANSLATION MISSING
|
||||
| test-core-crypto.cpp | Tests: cryptographic functions.
|
||||
| test-core-eval.cpp | テスト: 式の評価
|
||||
| test-core-hashtble.cpp | テスト: ハッシュテーブル
|
||||
| test-core-hdata.cpp | テスト: hdata
|
||||
|
|
|
@ -2074,67 +2074,6 @@ char *dump = weechat_string_hex_dump (string, strlen (string), 8, " >> ", NULL);
|
|||
[NOTE]
|
||||
スクリプト API ではこの関数を利用できません。
|
||||
|
||||
// TRANSLATION MISSING
|
||||
==== string_hash
|
||||
|
||||
_WeeChat バージョン 2.8 以上で利用可。_
|
||||
|
||||
Compute hash of data.
|
||||
|
||||
プロトタイプ:
|
||||
|
||||
[source,C]
|
||||
----
|
||||
int string_hash (const void *data, int data_size, const char *hash_algo, void *hash, int *hash_size);
|
||||
----
|
||||
|
||||
引数:
|
||||
|
||||
* _data_: the data to hash
|
||||
* _data_size_: number of bytes to hash in _data_
|
||||
* _hash_algo_: the hash algorithm, see table below
|
||||
* _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 below)
|
||||
* _hash_size_: pointer to a variable used to store the length of the hash computed
|
||||
(in bytes) (can be NULL)
|
||||
|
||||
Supported hash algorithms:
|
||||
|
||||
[width="100%",cols="2,2,3,6",options="header"]
|
||||
|===
|
||||
| Value | Algorithm | Hash size | Notes
|
||||
| `+crc32+` | CRC32 | 4 bytes (32 bits) | Not a hash algorithm in the cryptographic sense.
|
||||
| `+md5+` | MD5 | 16 bytes (128 bits) | *Weak*, not recommended for cryptography usage.
|
||||
| `+sha1+` | SHA-1 | 20 bytes (160 bits) | *Weak*, not recommended for cryptography usage.
|
||||
| `+sha224+` | SHA-224 | 28 bytes (224 bits) |
|
||||
| `+sha256+` | SHA-256 | 32 bytes (256 bits) |
|
||||
| `+sha384+` | SHA-384 | 48 bytes (384 bits) |
|
||||
| `+sha512+` | SHA-512 | 64 bytes (512 bits) |
|
||||
| `+sha3-224+` | SHA3-224 | 28 bytes (224 bits) |
|
||||
| `+sha3-256+` | SHA3-256 | 32 bytes (256 bits) |
|
||||
| `+sha3-384+` | SHA3-384 | 48 bytes (384 bits) |
|
||||
| `+sha3-512+` | SHA3-512 | 64 bytes (512 bits) |
|
||||
|===
|
||||
|
||||
戻り値:
|
||||
|
||||
* 成功した場合は 1、失敗した場合は 0
|
||||
|
||||
C 言語での使用例:
|
||||
|
||||
[source,C]
|
||||
----
|
||||
const char *data = "abcdefghijklmnopqrstuvwxyz";
|
||||
char hash[256 / 8];
|
||||
int rc, hash_size;
|
||||
rc = weechat_string_hash (data, strlen (data), "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 ではこの関数を利用できません。
|
||||
|
||||
==== string_is_command_char
|
||||
|
||||
_WeeChat バージョン 0.3.2 以上で利用可。_
|
||||
|
@ -3404,6 +3343,74 @@ free (string);
|
|||
[NOTE]
|
||||
スクリプト API ではこの関数を利用できません。
|
||||
|
||||
// TRANSLATION MISSING
|
||||
[[crypto]]
|
||||
=== Cryptography
|
||||
|
||||
Some cryptographic functions.
|
||||
|
||||
// TRANSLATION MISSING
|
||||
==== crypto_hash
|
||||
|
||||
_WeeChat バージョン 2.8 以上で利用可。_
|
||||
|
||||
Compute hash of data.
|
||||
|
||||
プロトタイプ:
|
||||
|
||||
[source,C]
|
||||
----
|
||||
int weechat_crypto_hash (const void *data, int data_size, const char *hash_algo,
|
||||
void *hash, int *hash_size);
|
||||
----
|
||||
|
||||
引数:
|
||||
|
||||
* _data_: the data to hash
|
||||
* _data_size_: number of bytes to hash in _data_
|
||||
* _hash_algo_: the hash algorithm, see table below
|
||||
* _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 below)
|
||||
* _hash_size_: pointer to a variable used to store the length of the hash computed
|
||||
(in bytes) (can be NULL)
|
||||
|
||||
Supported hash algorithms:
|
||||
|
||||
[width="100%",cols="2,2,3,6",options="header"]
|
||||
|===
|
||||
| Value | Algorithm | Hash size | Notes
|
||||
| `+crc32+` | CRC32 | 4 bytes (32 bits) | Not a hash algorithm in the cryptographic sense.
|
||||
| `+md5+` | MD5 | 16 bytes (128 bits) | *Weak*, not recommended for cryptography usage.
|
||||
| `+sha1+` | SHA-1 | 20 bytes (160 bits) | *Weak*, not recommended for cryptography usage.
|
||||
| `+sha224+` | SHA-224 | 28 bytes (224 bits) |
|
||||
| `+sha256+` | SHA-256 | 32 bytes (256 bits) |
|
||||
| `+sha384+` | SHA-384 | 48 bytes (384 bits) |
|
||||
| `+sha512+` | SHA-512 | 64 bytes (512 bits) |
|
||||
| `+sha3-224+` | SHA3-224 | 28 bytes (224 bits) |
|
||||
| `+sha3-256+` | SHA3-256 | 32 bytes (256 bits) |
|
||||
| `+sha3-384+` | SHA3-384 | 48 bytes (384 bits) |
|
||||
| `+sha3-512+` | SHA3-512 | 64 bytes (512 bits) |
|
||||
|===
|
||||
|
||||
戻り値:
|
||||
|
||||
* 成功した場合は 1、失敗した場合は 0
|
||||
|
||||
C 言語での使用例:
|
||||
|
||||
[source,C]
|
||||
----
|
||||
const char *data = "abcdefghijklmnopqrstuvwxyz";
|
||||
char hash[256 / 8];
|
||||
int rc, hash_size;
|
||||
rc = weechat_crypto_hash (data, strlen (data), "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 ではこの関数を利用できません。
|
||||
|
||||
[[directories]]
|
||||
=== ディレクトリ
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
./src/core/wee-config-file.c
|
||||
./src/core/wee-config-file.h
|
||||
./src/core/wee-config.h
|
||||
./src/core/wee-crypto.c
|
||||
./src/core/wee-crypto.h
|
||||
./src/core/wee-debug.c
|
||||
./src/core/wee-debug.h
|
||||
./src/core/wee-eval.c
|
||||
|
|
|
@ -52,6 +52,8 @@ SET(WEECHAT_SOURCES
|
|||
./src/core/wee-config-file.c
|
||||
./src/core/wee-config-file.h
|
||||
./src/core/wee-config.h
|
||||
./src/core/wee-crypto.c
|
||||
./src/core/wee-crypto.h
|
||||
./src/core/wee-debug.c
|
||||
./src/core/wee-debug.h
|
||||
./src/core/wee-eval.c
|
||||
|
|
|
@ -28,6 +28,7 @@ set(LIB_CORE_SRC
|
|||
wee-completion.c wee-completion.h
|
||||
wee-config.c wee-config.h
|
||||
wee-config-file.c wee-config-file.h
|
||||
wee-crypto.c wee-crypto.h
|
||||
wee-debug.c wee-debug.h
|
||||
wee-eval.c wee-eval.h
|
||||
wee-hashtable.c wee-hashtable.h
|
||||
|
|
|
@ -37,6 +37,8 @@ lib_weechat_core_a_SOURCES = weechat.c \
|
|||
wee-config.h \
|
||||
wee-config-file.c \
|
||||
wee-config-file.h \
|
||||
wee-crypto.c \
|
||||
wee-crypto.h \
|
||||
wee-debug.c \
|
||||
wee-debug.h \
|
||||
wee-eval.c \
|
||||
|
|
|
@ -0,0 +1,402 @@
|
|||
/*
|
||||
* wee-crypto.c - cryptographic functions
|
||||
*
|
||||
* Copyright (C) 2020 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* WeeChat is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "weechat.h"
|
||||
#include "wee-crypto.h"
|
||||
#include "wee-config-file.h"
|
||||
#include "wee-hashtable.h"
|
||||
#include "wee-string.h"
|
||||
#include "../plugins/plugin.h"
|
||||
|
||||
char *weecrypto_hash_algo_string[] = {
|
||||
"crc32",
|
||||
"md5",
|
||||
"sha1",
|
||||
"sha224", "sha256", "sha384", "sha512",
|
||||
"sha3-224", "sha3-256", "sha3-384", "sha3-512",
|
||||
NULL,
|
||||
};
|
||||
int weecrypto_hash_algo[] = {
|
||||
GCRY_MD_CRC32,
|
||||
GCRY_MD_MD5,
|
||||
GCRY_MD_SHA1,
|
||||
GCRY_MD_SHA224, GCRY_MD_SHA256, GCRY_MD_SHA384, GCRY_MD_SHA512,
|
||||
GCRY_MD_SHA3_224, GCRY_MD_SHA3_256, GCRY_MD_SHA3_384, GCRY_MD_SHA3_512,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Returns the hash algorithm with the name, or GCRY_MD_NONE if not found.
|
||||
*/
|
||||
|
||||
int
|
||||
weecrypto_get_hash_algo (const char *hash_algo)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!hash_algo)
|
||||
return GCRY_MD_NONE;
|
||||
|
||||
for (i = 0; weecrypto_hash_algo_string[i]; i++)
|
||||
{
|
||||
if (strcmp (weecrypto_hash_algo_string[i], hash_algo) == 0)
|
||||
return weecrypto_hash_algo[i];
|
||||
}
|
||||
|
||||
return GCRY_MD_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes hash of data using the given 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
|
||||
* GCRY_MD_SHA3_256 256 bits == 32 bytes
|
||||
* GCRY_MD_SHA3_384 384 bits == 48 bytes
|
||||
* GCRY_MD_SHA3_512 512 bits == 64 bytes
|
||||
*
|
||||
* 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 if OK, 0 if error.
|
||||
*/
|
||||
|
||||
int
|
||||
weecrypto_hash (const void *data, int data_size, int hash_algo,
|
||||
void *hash, int *hash_size)
|
||||
{
|
||||
gcry_md_hd_t *hd_md;
|
||||
int rc, hd_md_opened, algo_size;
|
||||
unsigned char *ptr_hash;
|
||||
|
||||
rc = 0;
|
||||
hd_md = NULL;
|
||||
hd_md_opened = 0;
|
||||
|
||||
if (!hash)
|
||||
goto hash_end;
|
||||
|
||||
if (hash_size)
|
||||
*hash_size = 0;
|
||||
|
||||
if (!data || (data_size < 1))
|
||||
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;
|
||||
|
||||
gcry_md_write (*hd_md, data, data_size);
|
||||
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);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes PKCS#5 Passphrase Based Key Derivation Function number 2 (PBKDF2)
|
||||
* hash of data.
|
||||
*
|
||||
* The hash size depends on the algorithm, common ones are:
|
||||
*
|
||||
* GCRY_MD_SHA1 160 bits == 20 bytes
|
||||
* GCRY_MD_SHA256 256 bits == 32 bytes
|
||||
* GCRY_MD_SHA512 512 bits == 64 bytes
|
||||
*
|
||||
* 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 if OK, 0 if error.
|
||||
*/
|
||||
|
||||
int
|
||||
weecrypto_hash_pbkdf2 (const void *data, int data_size, int hash_subalgo,
|
||||
const void *salt, int salt_size, int iterations,
|
||||
void *hash, int *hash_size)
|
||||
{
|
||||
int rc, algo_size;
|
||||
|
||||
rc = 0;
|
||||
|
||||
if (!hash)
|
||||
goto hash_pbkdf2_end;
|
||||
|
||||
if (hash_size)
|
||||
*hash_size = 0;
|
||||
|
||||
if (!data || (data_size < 1) || !salt || (salt_size < 1)
|
||||
|| (iterations < 1))
|
||||
{
|
||||
goto hash_pbkdf2_end;
|
||||
}
|
||||
|
||||
algo_size = gcry_md_get_algo_dlen (hash_subalgo);
|
||||
if (gcry_kdf_derive (data, data_size, GCRY_KDF_PBKDF2, hash_subalgo,
|
||||
salt, salt_size, iterations,
|
||||
algo_size, hash) != 0)
|
||||
{
|
||||
goto hash_pbkdf2_end;
|
||||
}
|
||||
|
||||
if (hash_size)
|
||||
*hash_size = algo_size;
|
||||
|
||||
rc = 1;
|
||||
|
||||
hash_pbkdf2_end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates a Time-based One-Time Password (TOTP), as described
|
||||
* in the RFC 6238.
|
||||
*
|
||||
* Returns:
|
||||
* 1: OK
|
||||
* 0: error
|
||||
*/
|
||||
|
||||
int
|
||||
weecrypto_totp_generate_internal (const char *secret, int length_secret,
|
||||
uint64_t moving_factor, int digits,
|
||||
char *result)
|
||||
{
|
||||
gcry_md_hd_t hd_md;
|
||||
uint64_t moving_factor_swapped;
|
||||
unsigned char *ptr_hash;
|
||||
char hash[20];
|
||||
int offset, length;
|
||||
unsigned long bin_code;
|
||||
|
||||
if (gcry_md_open (&hd_md, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC) != 0)
|
||||
return 0;
|
||||
|
||||
if (gcry_md_setkey (hd_md, secret, length_secret) != 0)
|
||||
{
|
||||
gcry_md_close (hd_md);
|
||||
return 0;
|
||||
}
|
||||
|
||||
moving_factor_swapped = (moving_factor >> 56)
|
||||
| ((moving_factor << 40) & 0x00FF000000000000)
|
||||
| ((moving_factor << 24) & 0x0000FF0000000000)
|
||||
| ((moving_factor << 8) & 0x000000FF00000000)
|
||||
| ((moving_factor >> 8) & 0x00000000FF000000)
|
||||
| ((moving_factor >> 24) & 0x0000000000FF0000)
|
||||
| ((moving_factor >> 40) & 0x000000000000FF00)
|
||||
| (moving_factor << 56);
|
||||
|
||||
gcry_md_write (hd_md,
|
||||
&moving_factor_swapped, sizeof (moving_factor_swapped));
|
||||
|
||||
ptr_hash = gcry_md_read (hd_md, GCRY_MD_SHA1);
|
||||
if (!ptr_hash)
|
||||
{
|
||||
gcry_md_close (hd_md);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy (hash, ptr_hash, sizeof (hash));
|
||||
|
||||
gcry_md_close (hd_md);
|
||||
|
||||
offset = hash[19] & 0xf;
|
||||
bin_code = (hash[offset] & 0x7f) << 24
|
||||
| (hash[offset+1] & 0xff) << 16
|
||||
| (hash[offset+2] & 0xff) << 8
|
||||
| (hash[offset+3] & 0xff);
|
||||
|
||||
bin_code %= (unsigned long)(pow (10, digits));
|
||||
|
||||
length = snprintf (result, digits + 1, "%.*lu", digits, bin_code);
|
||||
if (length != digits)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates a Time-based One-Time Password (TOTP), as described
|
||||
* in the RFC 6238.
|
||||
*
|
||||
* Returns the password as string, NULL if error.
|
||||
*
|
||||
* Note: result must be freed after use.
|
||||
*/
|
||||
|
||||
char *
|
||||
weecrypto_totp_generate (const char *secret_base32, time_t totp_time,
|
||||
int digits)
|
||||
{
|
||||
char *result, *secret;
|
||||
int length_secret, rc;
|
||||
uint64_t moving_factor;
|
||||
|
||||
secret = NULL;
|
||||
result = NULL;
|
||||
|
||||
if (!secret_base32 || !secret_base32[0]
|
||||
|| (digits < WEECRYPTO_TOTP_MIN_DIGITS)
|
||||
|| (digits > WEECRYPTO_TOTP_MAX_DIGITS))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
secret = malloc ((strlen (secret_base32) * 4) + 16 + 1);
|
||||
if (!secret)
|
||||
goto error;
|
||||
|
||||
length_secret = string_base32_decode (secret_base32, secret);
|
||||
if (length_secret < 0)
|
||||
goto error;
|
||||
|
||||
result = malloc (digits + 1);
|
||||
if (!result)
|
||||
goto error;
|
||||
|
||||
if (totp_time == 0)
|
||||
totp_time = time (NULL);
|
||||
|
||||
moving_factor = totp_time / 30;
|
||||
|
||||
rc = weecrypto_totp_generate_internal (secret, length_secret,
|
||||
moving_factor, digits, result);
|
||||
if (!rc)
|
||||
goto error;
|
||||
|
||||
free (secret);
|
||||
|
||||
return result;
|
||||
|
||||
error:
|
||||
if (secret)
|
||||
free (secret);
|
||||
if (result)
|
||||
free (result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validates a Time-based One-Time Password (TOTP).
|
||||
*
|
||||
* Returns:
|
||||
* 1: OTP is OK
|
||||
* 0: OTP is invalid
|
||||
*/
|
||||
|
||||
int
|
||||
weecrypto_totp_validate (const char *secret_base32, time_t totp_time,
|
||||
int window, const char *otp)
|
||||
{
|
||||
char *secret, str_otp[16];
|
||||
int length_secret, digits, rc, otp_ok;
|
||||
uint64_t i, moving_factor;
|
||||
|
||||
secret = NULL;
|
||||
|
||||
if (!secret_base32 || !secret_base32[0] || (window < 0) || !otp || !otp[0])
|
||||
goto error;
|
||||
|
||||
digits = strlen (otp);
|
||||
if ((digits < WEECRYPTO_TOTP_MIN_DIGITS)
|
||||
|| (digits > WEECRYPTO_TOTP_MAX_DIGITS))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
secret = malloc (strlen (secret_base32) + 1);
|
||||
if (!secret)
|
||||
goto error;
|
||||
|
||||
length_secret = string_base32_decode (secret_base32, secret);
|
||||
if (length_secret < 0)
|
||||
goto error;
|
||||
|
||||
if (totp_time == 0)
|
||||
totp_time = time (NULL);
|
||||
|
||||
moving_factor = totp_time / 30;
|
||||
|
||||
otp_ok = 0;
|
||||
|
||||
for (i = moving_factor - window; i <= moving_factor + window; i++)
|
||||
{
|
||||
rc = weecrypto_totp_generate_internal (secret, length_secret,
|
||||
i, digits, str_otp);
|
||||
if (rc && (strcmp (str_otp, otp) == 0))
|
||||
{
|
||||
otp_ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free (secret);
|
||||
|
||||
return otp_ok;
|
||||
|
||||
error:
|
||||
if (secret)
|
||||
free (secret);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) 2020 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* WeeChat is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WEECHAT_CRYPTO_H
|
||||
#define WEECHAT_CRYPTO_H
|
||||
|
||||
#define WEECRYPTO_TOTP_MIN_DIGITS 4
|
||||
#define WEECRYPTO_TOTP_MAX_DIGITS 10
|
||||
|
||||
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_pbkdf2 (const void *data, int data_size,
|
||||
int hash_subalgo,
|
||||
const void *salt, int salt_size,
|
||||
int iterations,
|
||||
void *hash, int *hash_size);
|
||||
extern char *weecrypto_totp_generate (const char *secret, time_t totp_time,
|
||||
int digits);
|
||||
extern int weecrypto_totp_validate (const char *secret, time_t totp_time,
|
||||
int window, const char *otp);
|
||||
|
||||
#endif /* WEECHAT_CRYPTO_H */
|
|
@ -25,13 +25,11 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "weechat.h"
|
||||
#include "wee-config-file.h"
|
||||
#include "wee-crypto.h"
|
||||
#include "wee-hashtable.h"
|
||||
#include "wee-secure.h"
|
||||
#include "wee-secure-config.h"
|
||||
|
@ -65,139 +63,6 @@ char *secure_decrypt_error[] = { "memory", "buffer", "key", "cipher", "setkey",
|
|||
int secure_data_encrypted = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Computes hash of data using the given 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
|
||||
* GCRY_MD_SHA3_256 256 bits == 32 bytes
|
||||
* GCRY_MD_SHA3_384 384 bits == 48 bytes
|
||||
* GCRY_MD_SHA3_512 512 bits == 64 bytes
|
||||
*
|
||||
* 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 if OK, 0 if error.
|
||||
*/
|
||||
|
||||
int
|
||||
secure_hash (const void *data, int data_size, int hash_algo,
|
||||
void *hash, int *hash_size)
|
||||
{
|
||||
gcry_md_hd_t *hd_md;
|
||||
int rc, hd_md_opened, algo_size;
|
||||
unsigned char *ptr_hash;
|
||||
|
||||
rc = 0;
|
||||
hd_md = NULL;
|
||||
hd_md_opened = 0;
|
||||
|
||||
if (!hash)
|
||||
goto hash_end;
|
||||
|
||||
if (hash_size)
|
||||
*hash_size = 0;
|
||||
|
||||
if (!data || (data_size < 1))
|
||||
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;
|
||||
|
||||
gcry_md_write (*hd_md, data, data_size);
|
||||
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);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes PKCS#5 Passphrase Based Key Derivation Function number 2 (PBKDF2)
|
||||
* hash of data, as binary buffer.
|
||||
*
|
||||
* The hash size depends on the algorithm, common ones are:
|
||||
*
|
||||
* GCRY_MD_SHA1 160 bits == 20 bytes
|
||||
* GCRY_MD_SHA256 256 bits == 32 bytes
|
||||
* GCRY_MD_SHA512 512 bits == 64 bytes
|
||||
*
|
||||
* 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 if OK, 0 if error.
|
||||
*/
|
||||
|
||||
int
|
||||
secure_hash_pbkdf2 (const void *data, int data_size, int hash_subalgo,
|
||||
const void *salt, int salt_size, int iterations,
|
||||
void *hash, int *hash_size)
|
||||
{
|
||||
int rc, algo_size;
|
||||
|
||||
rc = 0;
|
||||
|
||||
if (!hash)
|
||||
goto hash_pbkdf2_end;
|
||||
|
||||
if (hash_size)
|
||||
*hash_size = 0;
|
||||
|
||||
if (!data || (data_size < 1) || !salt || (salt_size < 1)
|
||||
|| (iterations < 1))
|
||||
{
|
||||
goto hash_pbkdf2_end;
|
||||
}
|
||||
|
||||
algo_size = gcry_md_get_algo_dlen (hash_subalgo);
|
||||
if (gcry_kdf_derive (data, data_size, GCRY_KDF_PBKDF2, hash_subalgo,
|
||||
salt, salt_size, iterations,
|
||||
algo_size, hash) != 0)
|
||||
{
|
||||
goto hash_pbkdf2_end;
|
||||
}
|
||||
|
||||
if (hash_size)
|
||||
*hash_size = algo_size;
|
||||
|
||||
rc = 1;
|
||||
|
||||
hash_pbkdf2_end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Derives a key from salt + passphrase (using a hash).
|
||||
*
|
||||
|
@ -228,7 +93,7 @@ secure_derive_key (const char *salt, const char *passphrase,
|
|||
memcpy (buffer + SECURE_SALT_SIZE, passphrase, strlen (passphrase));
|
||||
|
||||
/* compute hash of buffer */
|
||||
if (!secure_hash (buffer, length, GCRY_MD_SHA512, hash, &length_hash))
|
||||
if (!weecrypto_hash (buffer, length, GCRY_MD_SHA512, hash, &length_hash))
|
||||
{
|
||||
free (buffer);
|
||||
return 0;
|
||||
|
@ -628,195 +493,6 @@ secure_decrypt_data_not_decrypted (const char *passphrase)
|
|||
return num_ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates a Time-based One-Time Password (TOTP), as described
|
||||
* in the RFC 6238.
|
||||
*
|
||||
* Returns:
|
||||
* 1: OK
|
||||
* 0: error
|
||||
*/
|
||||
|
||||
int
|
||||
secure_totp_generate_internal (const char *secret, int length_secret,
|
||||
uint64_t moving_factor, int digits,
|
||||
char *result)
|
||||
{
|
||||
gcry_md_hd_t hd_md;
|
||||
uint64_t moving_factor_swapped;
|
||||
unsigned char *ptr_hash;
|
||||
char hash[20];
|
||||
int offset, length;
|
||||
unsigned long bin_code;
|
||||
|
||||
if (gcry_md_open (&hd_md, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC) != 0)
|
||||
return 0;
|
||||
|
||||
if (gcry_md_setkey (hd_md, secret, length_secret) != 0)
|
||||
{
|
||||
gcry_md_close (hd_md);
|
||||
return 0;
|
||||
}
|
||||
|
||||
moving_factor_swapped = (moving_factor >> 56)
|
||||
| ((moving_factor << 40) & 0x00FF000000000000)
|
||||
| ((moving_factor << 24) & 0x0000FF0000000000)
|
||||
| ((moving_factor << 8) & 0x000000FF00000000)
|
||||
| ((moving_factor >> 8) & 0x00000000FF000000)
|
||||
| ((moving_factor >> 24) & 0x0000000000FF0000)
|
||||
| ((moving_factor >> 40) & 0x000000000000FF00)
|
||||
| (moving_factor << 56);
|
||||
|
||||
gcry_md_write (hd_md,
|
||||
&moving_factor_swapped, sizeof (moving_factor_swapped));
|
||||
|
||||
ptr_hash = gcry_md_read (hd_md, GCRY_MD_SHA1);
|
||||
if (!ptr_hash)
|
||||
{
|
||||
gcry_md_close (hd_md);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy (hash, ptr_hash, sizeof (hash));
|
||||
|
||||
gcry_md_close (hd_md);
|
||||
|
||||
offset = hash[19] & 0xf;
|
||||
bin_code = (hash[offset] & 0x7f) << 24
|
||||
| (hash[offset+1] & 0xff) << 16
|
||||
| (hash[offset+2] & 0xff) << 8
|
||||
| (hash[offset+3] & 0xff);
|
||||
|
||||
bin_code %= (unsigned long)(pow (10, digits));
|
||||
|
||||
length = snprintf (result, digits + 1, "%.*lu", digits, bin_code);
|
||||
if (length != digits)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates a Time-based One-Time Password (TOTP), as described
|
||||
* in the RFC 6238.
|
||||
*
|
||||
* Returns the password as string, NULL if error.
|
||||
*
|
||||
* Note: result must be freed after use.
|
||||
*/
|
||||
|
||||
char *
|
||||
secure_totp_generate (const char *secret_base32, time_t totp_time, int digits)
|
||||
{
|
||||
char *result, *secret;
|
||||
int length_secret, rc;
|
||||
uint64_t moving_factor;
|
||||
|
||||
secret = NULL;
|
||||
result = NULL;
|
||||
|
||||
if (!secret_base32 || !secret_base32[0]
|
||||
|| (digits < SECURE_TOTP_MIN_DIGITS)
|
||||
|| (digits > SECURE_TOTP_MAX_DIGITS))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
secret = malloc ((strlen (secret_base32) * 4) + 16 + 1);
|
||||
if (!secret)
|
||||
goto error;
|
||||
|
||||
length_secret = string_base32_decode (secret_base32, secret);
|
||||
if (length_secret < 0)
|
||||
goto error;
|
||||
|
||||
result = malloc (digits + 1);
|
||||
if (!result)
|
||||
goto error;
|
||||
|
||||
if (totp_time == 0)
|
||||
totp_time = time (NULL);
|
||||
|
||||
moving_factor = totp_time / 30;
|
||||
|
||||
rc = secure_totp_generate_internal (secret, length_secret,
|
||||
moving_factor, digits, result);
|
||||
if (!rc)
|
||||
goto error;
|
||||
|
||||
free (secret);
|
||||
|
||||
return result;
|
||||
|
||||
error:
|
||||
if (secret)
|
||||
free (secret);
|
||||
if (result)
|
||||
free (result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validates a Time-based One-Time Password (TOTP).
|
||||
*
|
||||
* Returns:
|
||||
* 1: OTP is OK
|
||||
* 0: OTP is invalid
|
||||
*/
|
||||
|
||||
int
|
||||
secure_totp_validate (const char *secret_base32, time_t totp_time, int window,
|
||||
const char *otp)
|
||||
{
|
||||
char *secret, str_otp[16];
|
||||
int length_secret, digits, rc, otp_ok;
|
||||
uint64_t i, moving_factor;
|
||||
|
||||
secret = NULL;
|
||||
|
||||
if (!secret_base32 || !secret_base32[0] || (window < 0) || !otp || !otp[0])
|
||||
goto error;
|
||||
|
||||
digits = strlen (otp);
|
||||
if ((digits < SECURE_TOTP_MIN_DIGITS) || (digits > SECURE_TOTP_MAX_DIGITS))
|
||||
goto error;
|
||||
|
||||
secret = malloc (strlen (secret_base32) + 1);
|
||||
if (!secret)
|
||||
goto error;
|
||||
|
||||
length_secret = string_base32_decode (secret_base32, secret);
|
||||
if (length_secret < 0)
|
||||
goto error;
|
||||
|
||||
if (totp_time == 0)
|
||||
totp_time = time (NULL);
|
||||
|
||||
moving_factor = totp_time / 30;
|
||||
|
||||
otp_ok = 0;
|
||||
|
||||
for (i = moving_factor - window; i <= moving_factor + window; i++)
|
||||
{
|
||||
rc = secure_totp_generate_internal (secret, length_secret,
|
||||
i, digits, str_otp);
|
||||
if (rc && (strcmp (str_otp, otp) == 0))
|
||||
{
|
||||
otp_ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free (secret);
|
||||
|
||||
return otp_ok;
|
||||
|
||||
error:
|
||||
if (secret)
|
||||
free (secret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes secured data.
|
||||
*
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#define SECURE_SALT_DEFAULT "WeeChat!"
|
||||
#define SECURE_DATA_PASSPHRASE_FLAG "__passphrase__"
|
||||
#define SECURE_SALT_SIZE 8
|
||||
#define SECURE_TOTP_MIN_DIGITS 4
|
||||
#define SECURE_TOTP_MAX_DIGITS 10
|
||||
|
||||
enum t_secure_config_hash_algo
|
||||
{
|
||||
|
@ -55,13 +53,6 @@ extern int secure_cipher[];
|
|||
extern int secure_data_encrypted;
|
||||
extern char *secure_decrypt_error[];
|
||||
|
||||
extern int secure_hash (const void *data, int data_size, int hash_algo,
|
||||
void *hash, int *hash_size);
|
||||
extern int secure_hash_pbkdf2 (const void *data, int data_size,
|
||||
int hash_subalgo,
|
||||
const void *salt, int salt_size,
|
||||
int iterations,
|
||||
void *hash, int *hash_size);
|
||||
extern int secure_encrypt_data (const char *data, int length_data,
|
||||
int hash_algo, int cipher,
|
||||
const char *passphrase, char **encrypted,
|
||||
|
@ -71,10 +62,6 @@ extern int secure_decrypt_data (const char *buffer, int length_buffer,
|
|||
const char *passphrase, char **decrypted,
|
||||
int *length_decrypted);
|
||||
extern int secure_decrypt_data_not_decrypted (const char *passphrase);
|
||||
extern char *secure_totp_generate (const char *secret, time_t totp_time,
|
||||
int digits);
|
||||
extern int secure_totp_validate (const char *secret, time_t totp_time,
|
||||
int window, const char *otp);
|
||||
extern int secure_init ();
|
||||
extern void secure_end ();
|
||||
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
#include "wee-config.h"
|
||||
#include "wee-eval.h"
|
||||
#include "wee-hashtable.h"
|
||||
#include "wee-secure.h"
|
||||
#include "wee-utf8.h"
|
||||
#include "../gui/gui-chat.h"
|
||||
#include "../gui/gui-color.h"
|
||||
|
@ -65,22 +64,6 @@
|
|||
((c >= 'A') && (c <= 'F')) ? c - 'A' + 10 : \
|
||||
c - '0')
|
||||
|
||||
char *string_hash_algo_string[] = {
|
||||
"crc32",
|
||||
"md5",
|
||||
"sha1",
|
||||
"sha224", "sha256", "sha384", "sha512",
|
||||
"sha3-224", "sha3-256", "sha3-384", "sha3-512",
|
||||
NULL,
|
||||
};
|
||||
int string_hash_algo[] = {
|
||||
GCRY_MD_CRC32,
|
||||
GCRY_MD_MD5,
|
||||
GCRY_MD_SHA1,
|
||||
GCRY_MD_SHA224, GCRY_MD_SHA256, GCRY_MD_SHA384, GCRY_MD_SHA512,
|
||||
GCRY_MD_SHA3_224, GCRY_MD_SHA3_256, GCRY_MD_SHA3_384, GCRY_MD_SHA3_512,
|
||||
};
|
||||
|
||||
struct t_hashtable *string_hashtable_shared = NULL;
|
||||
|
||||
|
||||
|
@ -3422,53 +3405,6 @@ end:
|
|||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the hash algorithm with the name, or GCRY_MD_NONE if not found.
|
||||
*/
|
||||
|
||||
int
|
||||
string_get_hash_algo (const char *hash_algo)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!hash_algo)
|
||||
return GCRY_MD_NONE;
|
||||
|
||||
for (i = 0; string_hash_algo_string[i]; i++)
|
||||
{
|
||||
if (strcmp (string_hash_algo_string[i], hash_algo) == 0)
|
||||
return string_hash_algo[i];
|
||||
}
|
||||
|
||||
return GCRY_MD_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes hash data.
|
||||
*/
|
||||
|
||||
int
|
||||
string_hash (const void *data, int data_size, const char *hash_algo,
|
||||
void *hash, int *hash_size)
|
||||
{
|
||||
int algo;
|
||||
|
||||
if (!hash)
|
||||
return 0;
|
||||
|
||||
if (hash_size)
|
||||
*hash_size = 0;
|
||||
|
||||
if (!data || (data_size < 1) || !hash_algo)
|
||||
return 0;
|
||||
|
||||
algo = string_get_hash_algo (hash_algo);
|
||||
if (algo == GCRY_MD_NONE)
|
||||
return 0;
|
||||
|
||||
return secure_hash (data, data_size, algo, hash, hash_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if a string is a command.
|
||||
*
|
||||
|
|
|
@ -118,8 +118,6 @@ extern int string_base64_decode (const char *from, char *to);
|
|||
extern char *string_hex_dump (const char *data, int data_size,
|
||||
int bytes_per_line,
|
||||
const char *prefix, const char *suffix);
|
||||
extern int string_hash (const void *data, int data_size,
|
||||
const char *hash_algo, void *hash, int *hash_size);
|
||||
extern int string_is_command_char (const char *string);
|
||||
extern const char *string_input_for_buffer (const char *string);
|
||||
extern char *string_replace_with_callback (const char *string,
|
||||
|
|
|
@ -31,10 +31,10 @@
|
|||
|
||||
#include "../core/weechat.h"
|
||||
#include "../core/wee-config.h"
|
||||
#include "../core/wee-crypto.h"
|
||||
#include "../core/wee-hook.h"
|
||||
#include "../core/wee-infolist.h"
|
||||
#include "../core/wee-proxy.h"
|
||||
#include "../core/wee-secure.h"
|
||||
#include "../core/wee-string.h"
|
||||
#include "../core/wee-url.h"
|
||||
#include "../core/wee-util.h"
|
||||
|
@ -780,7 +780,7 @@ plugin_api_info_totp_generate_cb (const void *pointer, void *data,
|
|||
digits = number;
|
||||
}
|
||||
|
||||
totp = secure_totp_generate (ptr_secret, totp_time, digits);
|
||||
totp = weecrypto_totp_generate (ptr_secret, totp_time, digits);
|
||||
if (!totp)
|
||||
goto error;
|
||||
|
||||
|
@ -853,7 +853,7 @@ plugin_api_info_totp_validate_cb (const void *pointer, void *data,
|
|||
window = number;
|
||||
}
|
||||
|
||||
rc = secure_totp_validate (ptr_secret, totp_time, window, ptr_otp);
|
||||
rc = weecrypto_totp_validate (ptr_secret, totp_time, window, ptr_otp);
|
||||
|
||||
snprintf (value, sizeof (value), "%d", rc);
|
||||
|
||||
|
|
|
@ -25,9 +25,11 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "../core/weechat.h"
|
||||
#include "../core/wee-config.h"
|
||||
#include "../core/wee-crypto.h"
|
||||
#include "../core/wee-hashtable.h"
|
||||
#include "../core/wee-hook.h"
|
||||
#include "../core/wee-infolist.h"
|
||||
|
@ -134,6 +136,32 @@ plugin_api_string_base_decode (int base, const char *from, char *to)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes hash of data using the given algorithm.
|
||||
*/
|
||||
|
||||
int
|
||||
plugin_api_crypto_hash (const void *data, int data_size, const char *hash_algo,
|
||||
void *hash, int *hash_size)
|
||||
{
|
||||
int algo;
|
||||
|
||||
if (!hash)
|
||||
return 0;
|
||||
|
||||
if (hash_size)
|
||||
*hash_size = 0;
|
||||
|
||||
if (!data || (data_size < 1) || !hash_algo)
|
||||
return 0;
|
||||
|
||||
algo = weecrypto_get_hash_algo (hash_algo);
|
||||
if (algo == GCRY_MD_NONE)
|
||||
return 0;
|
||||
|
||||
return weecrypto_hash (data, data_size, algo, hash, hash_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Frees an option.
|
||||
*/
|
||||
|
|
|
@ -33,6 +33,11 @@ extern int plugin_api_string_base_encode (int base, const char *from,
|
|||
extern int plugin_api_string_base_decode (int base, const char *from,
|
||||
char *to);
|
||||
|
||||
/* crypto */
|
||||
extern int plugin_api_crypto_hash (const void *data, int data_size,
|
||||
const char *hash_algo,
|
||||
void *hash, int *hash_size);
|
||||
|
||||
/* config */
|
||||
extern void plugin_api_config_file_option_free (struct t_config_option *option);
|
||||
extern struct t_config_option *plugin_api_config_get (const char *option_name);
|
||||
|
|
|
@ -623,7 +623,6 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv)
|
|||
new_plugin->string_base_encode = &plugin_api_string_base_encode;
|
||||
new_plugin->string_base_decode = &plugin_api_string_base_decode;
|
||||
new_plugin->string_hex_dump = &string_hex_dump;
|
||||
new_plugin->string_hash = &string_hash;
|
||||
new_plugin->string_is_command_char = &string_is_command_char;
|
||||
new_plugin->string_input_for_buffer = &string_input_for_buffer;
|
||||
new_plugin->string_eval_expression = &eval_expression;
|
||||
|
@ -650,6 +649,8 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv)
|
|||
new_plugin->utf8_pos = &utf8_pos;
|
||||
new_plugin->utf8_strndup = &utf8_strndup;
|
||||
|
||||
new_plugin->crypto_hash = &plugin_api_crypto_hash;
|
||||
|
||||
new_plugin->mkdir_home = &util_mkdir_home;
|
||||
new_plugin->mkdir = &util_mkdir;
|
||||
new_plugin->mkdir_parents = &util_mkdir_parents;
|
||||
|
|
|
@ -207,7 +207,7 @@ relay_websocket_build_handshake (struct t_relay_client *client)
|
|||
snprintf (key, length, "%s%s", sec_websocket_key, WEBSOCKET_GUID);
|
||||
|
||||
/* compute 160-bit SHA1 on the key and encode it with base64 */
|
||||
if (!weechat_string_hash (key, strlen (key), "sha1", hash, &length_hash))
|
||||
if (!weechat_crypto_hash (key, strlen (key), "sha1", hash, &length_hash))
|
||||
{
|
||||
free (key);
|
||||
return NULL;
|
||||
|
|
|
@ -774,7 +774,7 @@ script_repo_sha512sum_file (const char *filename)
|
|||
}
|
||||
fclose (file);
|
||||
|
||||
if (!weechat_string_hash (data, st.st_size, "sha512", hash, &length_hash))
|
||||
if (!weechat_crypto_hash (data, st.st_size, "sha512", hash, &length_hash))
|
||||
{
|
||||
free (data);
|
||||
return NULL;
|
||||
|
|
|
@ -67,7 +67,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 "20200301-01"
|
||||
#define WEECHAT_PLUGIN_API_VERSION "20200301-02"
|
||||
|
||||
/* macros for defining plugin infos */
|
||||
#define WEECHAT_PLUGIN_NAME(__name) \
|
||||
|
@ -341,8 +341,6 @@ struct t_weechat_plugin
|
|||
char *(*string_hex_dump) (const char *data, int data_size,
|
||||
int bytes_per_line, const char *prefix,
|
||||
const char *suffix);
|
||||
int (*string_hash) (const void *data, int data_size,
|
||||
const char *hash_algo, void *hash, int *hash_size);
|
||||
int (*string_is_command_char) (const char *string);
|
||||
const char *(*string_input_for_buffer) (const char *string);
|
||||
char *(*string_eval_expression )(const char *expr,
|
||||
|
@ -374,6 +372,10 @@ struct t_weechat_plugin
|
|||
int (*utf8_pos) (const char *string, int real_pos);
|
||||
char *(*utf8_strndup) (const char *string, int length);
|
||||
|
||||
/* crypto */
|
||||
int (*crypto_hash) (const void *data, int data_size,
|
||||
const char *hash_algo, void *hash, int *hash_size);
|
||||
|
||||
/* directories/files */
|
||||
int (*mkdir_home) (const char *directory, int mode);
|
||||
int (*mkdir) (const char *directory, int mode);
|
||||
|
@ -1256,10 +1258,6 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin);
|
|||
(weechat_plugin->string_hex_dump)(__data, __data_size, \
|
||||
__bytes_per_line, __prefix, \
|
||||
__suffix)
|
||||
#define weechat_string_hash(__data, __data_size, __hash_algo, \
|
||||
__hash, __hash_size) \
|
||||
(weechat_plugin->string_hash)(__data, __data_size, __hash_algo, \
|
||||
__hash, __hash_size)
|
||||
#define weechat_string_is_command_char(__string) \
|
||||
(weechat_plugin->string_is_command_char)(__string)
|
||||
#define weechat_string_input_for_buffer(__string) \
|
||||
|
@ -1313,6 +1311,12 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin);
|
|||
#define weechat_utf8_strndup(__string, __length) \
|
||||
(weechat_plugin->utf8_strndup)(__string, __length)
|
||||
|
||||
/* crypto */
|
||||
#define weechat_crypto_hash(__data, __data_size, __hash_algo, \
|
||||
__hash, __hash_size) \
|
||||
(weechat_plugin->crypto_hash)(__data, __data_size, __hash_algo, \
|
||||
__hash, __hash_size)
|
||||
|
||||
/* directories */
|
||||
#define weechat_mkdir_home(__directory, __mode) \
|
||||
(weechat_plugin->mkdir_home)(__directory, __mode)
|
||||
|
|
|
@ -27,6 +27,7 @@ set(LIB_WEECHAT_UNIT_TESTS_CORE_SRC
|
|||
unit/test-plugins.cpp
|
||||
unit/core/test-core-arraylist.cpp
|
||||
unit/core/test-core-calc.cpp
|
||||
unit/core/test-core-crypto.cpp
|
||||
unit/core/test-core-eval.cpp
|
||||
unit/core/test-core-hashtable.cpp
|
||||
unit/core/test-core-hdata.cpp
|
||||
|
@ -38,7 +39,6 @@ set(LIB_WEECHAT_UNIT_TESTS_CORE_SRC
|
|||
unit/core/test-core-url.cpp
|
||||
unit/core/test-core-utf8.cpp
|
||||
unit/core/test-core-util.cpp
|
||||
unit/core/test-core.h
|
||||
unit/gui/test-gui-color.cpp
|
||||
unit/gui/test-gui-line.cpp
|
||||
unit/gui/test-gui-nick.cpp
|
||||
|
|
|
@ -24,6 +24,7 @@ noinst_LIBRARIES = lib_weechat_unit_tests_core.a
|
|||
lib_weechat_unit_tests_core_a_SOURCES = unit/test-plugins.cpp \
|
||||
unit/core/test-core-arraylist.cpp \
|
||||
unit/core/test-core-calc.cpp \
|
||||
unit/core/test-core-crypto.cpp \
|
||||
unit/core/test-core-eval.cpp \
|
||||
unit/core/test-core-hashtable.cpp \
|
||||
unit/core/test-core-hdata.cpp \
|
||||
|
@ -35,7 +36,6 @@ lib_weechat_unit_tests_core_a_SOURCES = unit/test-plugins.cpp \
|
|||
unit/core/test-core-url.cpp \
|
||||
unit/core/test-core-utf8.cpp \
|
||||
unit/core/test-core-util.cpp \
|
||||
unit/core/test-core.h \
|
||||
unit/gui/test-gui-color.cpp \
|
||||
unit/gui/test-gui-line.cpp \
|
||||
unit/gui/test-gui-nick.cpp \
|
||||
|
|
|
@ -62,6 +62,7 @@ extern "C"
|
|||
IMPORT_TEST_GROUP(Plugins);
|
||||
IMPORT_TEST_GROUP(CoreArraylist);
|
||||
IMPORT_TEST_GROUP(CoreCalc);
|
||||
IMPORT_TEST_GROUP(CoreCrypto);
|
||||
IMPORT_TEST_GROUP(CoreEval);
|
||||
IMPORT_TEST_GROUP(CoreHashtable);
|
||||
IMPORT_TEST_GROUP(CoreHdata);
|
||||
|
|
|
@ -0,0 +1,311 @@
|
|||
/*
|
||||
* test-core-crypto.cpp - test cryptographic functions
|
||||
*
|
||||
* Copyright (C) 2020 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* WeeChat is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "CppUTest/TestHarness.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <string.h>
|
||||
#include <gcrypt.h>
|
||||
#include "src/core/wee-crypto.h"
|
||||
#include "src/core/wee-string.h"
|
||||
|
||||
#define DATA_HASH "this is a test of hash function"
|
||||
#define DATA_HASH_CRC32 "ef26fe3e"
|
||||
#define DATA_HASH_MD5 "1197d121af621ac6a63cb8ef6b5dfa30"
|
||||
#define DATA_HASH_SHA1 "799d818061175b400dc5aaeb14b8d32cdef32ff0"
|
||||
#define DATA_HASH_SHA224 "637d21f3ba3f4e9fa9fb889dc990b31a658cb37b4aefb5144" \
|
||||
"70b016d"
|
||||
#define DATA_HASH_SHA256 "b9a4c3393dfac4330736684510378851e581c68add8eca841" \
|
||||
"10c31a33e694676"
|
||||
#define DATA_HASH_SHA384 "42853280be9b8409eed265f272bd580e2fbd448b7c7e236c7" \
|
||||
"f37dafec7906d51d982dc84ec70a4733eca49d86ac19455"
|
||||
#define DATA_HASH_SHA512 "4469190d4e0d1fdc0afb6f408d9873c89b8ce89cc4db79fe0" \
|
||||
"58255c55ad6821fa5e9bb068f9e578c8ae7cc825d85ff99c439d59e439bc589d95620a" \
|
||||
"1e6b8ae6e"
|
||||
#define DATA_HASH_SHA3_224 "26432a3a4ea998790be43386b1de417f88be43146a4af98" \
|
||||
"2a9627d10"
|
||||
#define DATA_HASH_SHA3_256 "226e3830306711cf653c1661765c304b37038e7457c35dd" \
|
||||
"14fca0f6a8ba1d2e3"
|
||||
#define DATA_HASH_SHA3_384 "77bc16f89c102efc783ddeccc71862fe919b66e1aaa88bd" \
|
||||
"2ba5f0bbe604fcb86c68f0e401d5d553597366cdd400595ba"
|
||||
#define DATA_HASH_SHA3_512 "31dfb5fc8f30ac7007acddc4fce562d408706833d0d2af2" \
|
||||
"e5f61a179099592927ff7d100e278406c7f98d42575001e26e153b135c21f7ef5b00c8" \
|
||||
"cef93ca048d"
|
||||
#define DATA_HASH_SALT "this is a salt of 32 bytes xxxxx"
|
||||
#define DATA_HASH_PBKDF2_SHA1_1000 "85ce23c8873830df8f0a96aa82ae7d7635dad12" \
|
||||
"7"
|
||||
#define DATA_HASH_PBKDF2_SHA1_100000 "f2c2a079007523df3a5a5c7b578073dff06ba" \
|
||||
"49f"
|
||||
#define DATA_HASH_PBKDF2_SHA256_1000 "0eb0a795537a8c37a2d7d7e50a076e07c9a8e" \
|
||||
"e9aa281669381af99fad198997c"
|
||||
#define DATA_HASH_PBKDF2_SHA256_100000 "b243ef60f9d9e7a6315f874053802cfb3b7" \
|
||||
"b5a3502d47cf7fd76b3ee5661fcff"
|
||||
#define DATA_HASH_PBKDF2_SHA512_1000 "03d8e9e86f3bbe20b88a600a5aa15f8cfbee0" \
|
||||
"a402af301e1714c25467a32489c773c71eddf5aa39f42823ecc54c9e9b015517b5f3c0" \
|
||||
"19bae9463a2d8fe527882"
|
||||
#define DATA_HASH_PBKDF2_SHA512_100000 "286cca5521b00a7398530fbf11a570401a8" \
|
||||
"0c901f1584cb493fcb75c49e5c30613c331ce318b34615a08be2fdcb9a3b4d3e9a5b62" \
|
||||
"e119db6941010533cdf73d3"
|
||||
|
||||
#define TOTP_SECRET "secretpasswordbase32"
|
||||
|
||||
#define WEE_CHECK_HASH(__result_code, __result_hash, \
|
||||
__data, __data_size, __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 (__data, __data_size, __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_subalgo, __salt, __salt_size, \
|
||||
__iterations) \
|
||||
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_pbkdf2 (__data, __data_size, \
|
||||
__hash_subalgo, \
|
||||
__salt, __salt_size, \
|
||||
__iterations, \
|
||||
hash, &hash_size)); \
|
||||
if (__result_hash) \
|
||||
{ \
|
||||
MEMCMP_EQUAL(hash_expected, hash, hash_size); \
|
||||
} \
|
||||
LONGS_EQUAL(hash_size_expected, hash_size);
|
||||
|
||||
#define WEE_CHECK_TOTP_GENERATE(__result, __secret, __time, __digits) \
|
||||
totp = weecrypto_totp_generate (__secret, __time, __digits); \
|
||||
if (__result == NULL) \
|
||||
{ \
|
||||
POINTERS_EQUAL(NULL, totp); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
STRCMP_EQUAL(__result, totp); \
|
||||
} \
|
||||
if (totp) \
|
||||
free (totp);
|
||||
|
||||
#define WEE_CHECK_TOTP_VALIDATE(__result, __secret, __time, __window, \
|
||||
__otp) \
|
||||
LONGS_EQUAL(__result, weecrypto_totp_validate (__secret, __time, \
|
||||
__window, __otp));
|
||||
}
|
||||
|
||||
TEST_GROUP(CoreCrypto)
|
||||
{
|
||||
};
|
||||
|
||||
/*
|
||||
* Tests functions:
|
||||
* weecrypto_hash
|
||||
*/
|
||||
|
||||
TEST(CoreCrypto, Hash)
|
||||
{
|
||||
const char *data = DATA_HASH;
|
||||
char hash_expected[4096], hash[4096];
|
||||
int data_size, hash_size_expected, hash_size;
|
||||
|
||||
data_size = strlen (data);
|
||||
|
||||
WEE_CHECK_HASH(0, NULL, NULL, 0, 0);
|
||||
WEE_CHECK_HASH(0, NULL, "test", 0, 0);
|
||||
|
||||
WEE_CHECK_HASH(1, DATA_HASH_CRC32, data, data_size, GCRY_MD_CRC32);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_MD5, data, data_size, GCRY_MD_MD5);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA1, data, data_size, GCRY_MD_SHA1);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA224, data, data_size, GCRY_MD_SHA224);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA256, data, data_size, GCRY_MD_SHA256);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA384, data, data_size, GCRY_MD_SHA384);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA512, data, data_size, GCRY_MD_SHA512);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA3_224, data, data_size, GCRY_MD_SHA3_224);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA3_256, data, data_size, GCRY_MD_SHA3_256);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA3_384, data, data_size, GCRY_MD_SHA3_384);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA3_512, data, data_size, GCRY_MD_SHA3_512);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests functions:
|
||||
* weecrypto_hash_pbkdf2
|
||||
*/
|
||||
|
||||
TEST(CoreCrypto, HashPbkdf2)
|
||||
{
|
||||
const char *data = DATA_HASH, *salt = DATA_HASH_SALT;
|
||||
char hash_expected[4096], hash[4096];
|
||||
int data_size, salt_size, hash_size_expected, hash_size;
|
||||
|
||||
data_size = strlen (data);
|
||||
salt_size = strlen (salt);
|
||||
|
||||
WEE_CHECK_HASH_PBKDF2(0, NULL, NULL, 0, 0, NULL, 0, 0);
|
||||
WEE_CHECK_HASH_PBKDF2(0, NULL, "test", 0, 0, NULL, 0, 0);
|
||||
WEE_CHECK_HASH_PBKDF2(0, NULL, "test", 4, GCRY_MD_SHA1, "salt", 4, 0);
|
||||
|
||||
/* SHA1 */
|
||||
WEE_CHECK_HASH_PBKDF2(1, DATA_HASH_PBKDF2_SHA1_1000,
|
||||
data, data_size,
|
||||
GCRY_MD_SHA1,
|
||||
DATA_HASH_SALT, salt_size,
|
||||
1000);
|
||||
WEE_CHECK_HASH_PBKDF2(1, DATA_HASH_PBKDF2_SHA1_100000,
|
||||
data, data_size,
|
||||
GCRY_MD_SHA1,
|
||||
DATA_HASH_SALT, salt_size,
|
||||
100000);
|
||||
|
||||
/* SHA256 */
|
||||
WEE_CHECK_HASH_PBKDF2(1, DATA_HASH_PBKDF2_SHA256_1000,
|
||||
data, data_size,
|
||||
GCRY_MD_SHA256,
|
||||
DATA_HASH_SALT, salt_size,
|
||||
1000);
|
||||
WEE_CHECK_HASH_PBKDF2(1, DATA_HASH_PBKDF2_SHA256_100000,
|
||||
data, data_size,
|
||||
GCRY_MD_SHA256,
|
||||
DATA_HASH_SALT, salt_size,
|
||||
100000);
|
||||
|
||||
/* SHA512 */
|
||||
WEE_CHECK_HASH_PBKDF2(1, DATA_HASH_PBKDF2_SHA512_1000,
|
||||
data, data_size,
|
||||
GCRY_MD_SHA512,
|
||||
DATA_HASH_SALT, salt_size,
|
||||
1000);
|
||||
WEE_CHECK_HASH_PBKDF2(1, DATA_HASH_PBKDF2_SHA512_100000,
|
||||
data, data_size,
|
||||
GCRY_MD_SHA512,
|
||||
DATA_HASH_SALT, salt_size,
|
||||
100000);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests functions:
|
||||
* weecrypto_totp_generate
|
||||
*/
|
||||
|
||||
TEST(CoreCrypto, TotpGenerate)
|
||||
{
|
||||
char *totp;
|
||||
|
||||
/* invalid secret */
|
||||
WEE_CHECK_TOTP_GENERATE(NULL, NULL, 0, 6);
|
||||
WEE_CHECK_TOTP_GENERATE(NULL, "", 0, 6);
|
||||
WEE_CHECK_TOTP_GENERATE(NULL, "not_in_base32_0189", 0, 6);
|
||||
|
||||
/* invalid number of digits (must be between 4 and 10) */
|
||||
WEE_CHECK_TOTP_GENERATE(NULL, TOTP_SECRET, 0, 3);
|
||||
WEE_CHECK_TOTP_GENERATE(NULL, TOTP_SECRET, 0, 11);
|
||||
|
||||
/* TOTP with 6 digits */
|
||||
WEE_CHECK_TOTP_GENERATE("065486", TOTP_SECRET, 1540624066, 6);
|
||||
WEE_CHECK_TOTP_GENERATE("640073", TOTP_SECRET, 1540624085, 6);
|
||||
WEE_CHECK_TOTP_GENERATE("725645", TOTP_SECRET, 1540624110, 6);
|
||||
|
||||
/* TOTP with 7 digits */
|
||||
WEE_CHECK_TOTP_GENERATE("0065486", TOTP_SECRET, 1540624066, 7);
|
||||
WEE_CHECK_TOTP_GENERATE("6640073", TOTP_SECRET, 1540624085, 7);
|
||||
WEE_CHECK_TOTP_GENERATE("4725645", TOTP_SECRET, 1540624110, 7);
|
||||
|
||||
/* TOTP with 8 digits */
|
||||
WEE_CHECK_TOTP_GENERATE("40065486", TOTP_SECRET, 1540624066, 8);
|
||||
WEE_CHECK_TOTP_GENERATE("16640073", TOTP_SECRET, 1540624085, 8);
|
||||
WEE_CHECK_TOTP_GENERATE("94725645", TOTP_SECRET, 1540624110, 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests functions:
|
||||
* weecrypto_totp_validate
|
||||
*/
|
||||
|
||||
TEST(CoreCrypto, TotpValidate)
|
||||
{
|
||||
/* invalid secret */
|
||||
WEE_CHECK_TOTP_VALIDATE(0, NULL, 0, 0, "123456");
|
||||
WEE_CHECK_TOTP_VALIDATE(0, "", 0, 0, "123456");
|
||||
WEE_CHECK_TOTP_VALIDATE(0, "not_in_base32_0189", 0, 0, "123456");
|
||||
|
||||
/* invalid window (must be ≥ 0) */
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 0, -1, "123456");
|
||||
|
||||
/* invalid OTP */
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 0, 0, NULL);
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 0, 0, "");
|
||||
|
||||
/* validation error (wrong OTP) */
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 0, "065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 1, "065486");
|
||||
|
||||
/* TOTP with 6 digits */
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624066, 0, "065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624085, 0, "640073");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624110, 0, "725645");
|
||||
|
||||
/* TOTP with 7 digits */
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624066, 0, "0065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624085, 0, "6640073");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624110, 0, "4725645");
|
||||
|
||||
/* TOTP with 7 digits */
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624066, 0, "40065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624085, 0, "16640073");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624110, 0, "94725645");
|
||||
|
||||
/* TOTP with 6 digits, using window */
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 0, "065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 1, "065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624110, 2, "065486");
|
||||
|
||||
/* TOTP with 7 digits, using window */
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 0, "0065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 1, "0065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624110, 2, "0065486");
|
||||
|
||||
/* TOTP with 8 digits, using window */
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 0, "40065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 1, "40065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624110, 2, "40065486");
|
||||
}
|
|
@ -25,7 +25,6 @@ extern "C"
|
|||
{
|
||||
#include <string.h>
|
||||
#include <gcrypt.h>
|
||||
#include "tests/unit/core/test-core.h"
|
||||
#include "src/core/wee-secure.h"
|
||||
#include "src/core/wee-string.h"
|
||||
|
||||
|
@ -33,71 +32,6 @@ extern "C"
|
|||
#define SECURE_PASSWORD "this_is_a_secret_password"
|
||||
#define TOTP_SECRET "secretpasswordbase32"
|
||||
|
||||
#define WEE_CHECK_HASH(__result_code, __result_hash, \
|
||||
__data, __data_size, __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, \
|
||||
secure_hash (__data, __data_size, __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_subalgo, __salt, __salt_size, \
|
||||
__iterations) \
|
||||
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, \
|
||||
secure_hash_pbkdf2 (__data, __data_size, \
|
||||
__hash_subalgo, \
|
||||
__salt, __salt_size, \
|
||||
__iterations, \
|
||||
hash, &hash_size)); \
|
||||
if (__result_hash) \
|
||||
{ \
|
||||
MEMCMP_EQUAL(hash_expected, hash, hash_size); \
|
||||
} \
|
||||
LONGS_EQUAL(hash_size_expected, hash_size);
|
||||
|
||||
#define WEE_CHECK_TOTP_GENERATE(__result, __secret, __time, __digits) \
|
||||
totp = secure_totp_generate (__secret, __time, __digits); \
|
||||
if (__result == NULL) \
|
||||
{ \
|
||||
POINTERS_EQUAL(NULL, totp); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
STRCMP_EQUAL(__result, totp); \
|
||||
} \
|
||||
if (totp) \
|
||||
free (totp);
|
||||
|
||||
#define WEE_CHECK_TOTP_VALIDATE(__result, __secret, __time, __window, \
|
||||
__otp) \
|
||||
LONGS_EQUAL(__result, secure_totp_validate (__secret, __time, \
|
||||
__window, __otp));
|
||||
|
||||
extern int secure_derive_key (const char *salt, const char *passphrase,
|
||||
unsigned char *key, int length_key);
|
||||
}
|
||||
|
@ -106,90 +40,6 @@ TEST_GROUP(CoreSecure)
|
|||
{
|
||||
};
|
||||
|
||||
/*
|
||||
* Tests functions:
|
||||
* secure_hash
|
||||
*/
|
||||
|
||||
TEST(CoreSecure, Hash)
|
||||
{
|
||||
const char *data = DATA_HASH;
|
||||
char hash_expected[4096], hash[4096];
|
||||
int data_size, hash_size_expected, hash_size;
|
||||
|
||||
data_size = strlen (data);
|
||||
|
||||
WEE_CHECK_HASH(0, NULL, NULL, 0, 0);
|
||||
WEE_CHECK_HASH(0, NULL, "test", 0, 0);
|
||||
|
||||
WEE_CHECK_HASH(1, DATA_HASH_CRC32, data, data_size, GCRY_MD_CRC32);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_MD5, data, data_size, GCRY_MD_MD5);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA1, data, data_size, GCRY_MD_SHA1);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA224, data, data_size, GCRY_MD_SHA224);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA256, data, data_size, GCRY_MD_SHA256);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA384, data, data_size, GCRY_MD_SHA384);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA512, data, data_size, GCRY_MD_SHA512);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA3_224, data, data_size, GCRY_MD_SHA3_224);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA3_256, data, data_size, GCRY_MD_SHA3_256);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA3_384, data, data_size, GCRY_MD_SHA3_384);
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA3_512, data, data_size, GCRY_MD_SHA3_512);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests functions:
|
||||
* secure_hash_pbkdf2
|
||||
*/
|
||||
|
||||
TEST(CoreSecure, HashPbkdf2)
|
||||
{
|
||||
const char *data = DATA_HASH, *salt = DATA_HASH_SALT;
|
||||
char hash_expected[4096], hash[4096];
|
||||
int data_size, salt_size, hash_size_expected, hash_size;
|
||||
|
||||
data_size = strlen (data);
|
||||
salt_size = strlen (salt);
|
||||
|
||||
WEE_CHECK_HASH_PBKDF2(0, NULL, NULL, 0, 0, NULL, 0, 0);
|
||||
WEE_CHECK_HASH_PBKDF2(0, NULL, "test", 0, 0, NULL, 0, 0);
|
||||
WEE_CHECK_HASH_PBKDF2(0, NULL, "test", 4, GCRY_MD_SHA1, "salt", 4, 0);
|
||||
|
||||
/* SHA1 */
|
||||
WEE_CHECK_HASH_PBKDF2(1, DATA_HASH_PBKDF2_SHA1_1000,
|
||||
data, data_size,
|
||||
GCRY_MD_SHA1,
|
||||
DATA_HASH_SALT, salt_size,
|
||||
1000);
|
||||
WEE_CHECK_HASH_PBKDF2(1, DATA_HASH_PBKDF2_SHA1_100000,
|
||||
data, data_size,
|
||||
GCRY_MD_SHA1,
|
||||
DATA_HASH_SALT, salt_size,
|
||||
100000);
|
||||
|
||||
/* SHA256 */
|
||||
WEE_CHECK_HASH_PBKDF2(1, DATA_HASH_PBKDF2_SHA256_1000,
|
||||
data, data_size,
|
||||
GCRY_MD_SHA256,
|
||||
DATA_HASH_SALT, salt_size,
|
||||
1000);
|
||||
WEE_CHECK_HASH_PBKDF2(1, DATA_HASH_PBKDF2_SHA256_100000,
|
||||
data, data_size,
|
||||
GCRY_MD_SHA256,
|
||||
DATA_HASH_SALT, salt_size,
|
||||
100000);
|
||||
|
||||
/* SHA512 */
|
||||
WEE_CHECK_HASH_PBKDF2(1, DATA_HASH_PBKDF2_SHA512_1000,
|
||||
data, data_size,
|
||||
GCRY_MD_SHA512,
|
||||
DATA_HASH_SALT, salt_size,
|
||||
1000);
|
||||
WEE_CHECK_HASH_PBKDF2(1, DATA_HASH_PBKDF2_SHA512_100000,
|
||||
data, data_size,
|
||||
GCRY_MD_SHA512,
|
||||
DATA_HASH_SALT, salt_size,
|
||||
100000);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests functions:
|
||||
* secure_derive_key
|
||||
|
@ -288,91 +138,3 @@ TEST(CoreSecure, EncryptDecryptData)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests functions:
|
||||
* secure_totp_generate
|
||||
*/
|
||||
|
||||
TEST(CoreSecure, TotpGenerate)
|
||||
{
|
||||
char *totp;
|
||||
|
||||
/* invalid secret */
|
||||
WEE_CHECK_TOTP_GENERATE(NULL, NULL, 0, 6);
|
||||
WEE_CHECK_TOTP_GENERATE(NULL, "", 0, 6);
|
||||
WEE_CHECK_TOTP_GENERATE(NULL, "not_in_base32_0189", 0, 6);
|
||||
|
||||
/* invalid number of digits (must be between 4 and 10) */
|
||||
WEE_CHECK_TOTP_GENERATE(NULL, TOTP_SECRET, 0, 3);
|
||||
WEE_CHECK_TOTP_GENERATE(NULL, TOTP_SECRET, 0, 11);
|
||||
|
||||
/* TOTP with 6 digits */
|
||||
WEE_CHECK_TOTP_GENERATE("065486", TOTP_SECRET, 1540624066, 6);
|
||||
WEE_CHECK_TOTP_GENERATE("640073", TOTP_SECRET, 1540624085, 6);
|
||||
WEE_CHECK_TOTP_GENERATE("725645", TOTP_SECRET, 1540624110, 6);
|
||||
|
||||
/* TOTP with 7 digits */
|
||||
WEE_CHECK_TOTP_GENERATE("0065486", TOTP_SECRET, 1540624066, 7);
|
||||
WEE_CHECK_TOTP_GENERATE("6640073", TOTP_SECRET, 1540624085, 7);
|
||||
WEE_CHECK_TOTP_GENERATE("4725645", TOTP_SECRET, 1540624110, 7);
|
||||
|
||||
/* TOTP with 8 digits */
|
||||
WEE_CHECK_TOTP_GENERATE("40065486", TOTP_SECRET, 1540624066, 8);
|
||||
WEE_CHECK_TOTP_GENERATE("16640073", TOTP_SECRET, 1540624085, 8);
|
||||
WEE_CHECK_TOTP_GENERATE("94725645", TOTP_SECRET, 1540624110, 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests functions:
|
||||
* secure_totp_validate
|
||||
*/
|
||||
|
||||
TEST(CoreSecure, TotpValidate)
|
||||
{
|
||||
/* invalid secret */
|
||||
WEE_CHECK_TOTP_VALIDATE(0, NULL, 0, 0, "123456");
|
||||
WEE_CHECK_TOTP_VALIDATE(0, "", 0, 0, "123456");
|
||||
WEE_CHECK_TOTP_VALIDATE(0, "not_in_base32_0189", 0, 0, "123456");
|
||||
|
||||
/* invalid window (must be ≥ 0) */
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 0, -1, "123456");
|
||||
|
||||
/* invalid OTP */
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 0, 0, NULL);
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 0, 0, "");
|
||||
|
||||
/* validation error (wrong OTP) */
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 0, "065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 1, "065486");
|
||||
|
||||
/* TOTP with 6 digits */
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624066, 0, "065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624085, 0, "640073");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624110, 0, "725645");
|
||||
|
||||
/* TOTP with 7 digits */
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624066, 0, "0065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624085, 0, "6640073");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624110, 0, "4725645");
|
||||
|
||||
/* TOTP with 7 digits */
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624066, 0, "40065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624085, 0, "16640073");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624110, 0, "94725645");
|
||||
|
||||
/* TOTP with 6 digits, using window */
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 0, "065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 1, "065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624110, 2, "065486");
|
||||
|
||||
/* TOTP with 7 digits, using window */
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 0, "0065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 1, "0065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624110, 2, "0065486");
|
||||
|
||||
/* TOTP with 8 digits, using window */
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 0, "40065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(0, TOTP_SECRET, 1540624110, 1, "40065486");
|
||||
WEE_CHECK_TOTP_VALIDATE(1, TOTP_SECRET, 1540624110, 2, "40065486");
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ extern "C"
|
|||
#include <string.h>
|
||||
#include <regex.h>
|
||||
#include "tests/tests.h"
|
||||
#include "tests/unit/core/test-core.h"
|
||||
#include "src/core/weechat.h"
|
||||
#include "src/core/wee-string.h"
|
||||
#include "src/core/wee-hashtable.h"
|
||||
|
@ -108,27 +107,6 @@ extern "C"
|
|||
STRCMP_EQUAL(__result, str); \
|
||||
free (str);
|
||||
|
||||
#define WEE_CHECK_HASH(__result_code, __result_hash, \
|
||||
__data, __data_size, __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, \
|
||||
string_hash (__data, __data_size, __hash_algo, \
|
||||
hash, &hash_size)); \
|
||||
if (__result_hash) \
|
||||
{ \
|
||||
MEMCMP_EQUAL(hash_expected, hash, hash_size); \
|
||||
} \
|
||||
LONGS_EQUAL(hash_size_expected, hash_size);
|
||||
|
||||
extern struct t_hashtable *string_hashtable_shared;
|
||||
|
||||
TEST_GROUP(CoreString)
|
||||
|
@ -1932,37 +1910,6 @@ TEST(CoreString, Hex_dump)
|
|||
str);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests functions:
|
||||
* string_hash
|
||||
*/
|
||||
|
||||
TEST(CoreString, Hash)
|
||||
{
|
||||
const char *data = DATA_HASH;
|
||||
char hash_expected[4096], hash[4096];
|
||||
int data_size, hash_size_expected, hash_size;
|
||||
|
||||
data_size = strlen (data);
|
||||
|
||||
WEE_CHECK_HASH(0, NULL, NULL, 0, NULL);
|
||||
WEE_CHECK_HASH(0, NULL, DATA_HASH, 0, NULL);
|
||||
WEE_CHECK_HASH(0, NULL, DATA_HASH, data_size, NULL);
|
||||
WEE_CHECK_HASH(0, NULL, DATA_HASH, data_size, "not_an_algo");
|
||||
|
||||
WEE_CHECK_HASH(1, DATA_HASH_CRC32, data, data_size, "crc32");
|
||||
WEE_CHECK_HASH(1, DATA_HASH_MD5, data, data_size, "md5");
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA1, data, data_size, "sha1");
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA224, data, data_size, "sha224");
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA256, data, data_size, "sha256");
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA384, data, data_size, "sha384");
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA512, data, data_size, "sha512");
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA3_224, data, data_size, "sha3-224");
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA3_256, data, data_size, "sha3-256");
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA3_384, data, data_size, "sha3-384");
|
||||
WEE_CHECK_HASH(1, DATA_HASH_SHA3_512, data, data_size, "sha3-512");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests functions:
|
||||
* string_is_command_char
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2020 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* WeeChat is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WEECHAT_TEST_UNIT_CORE_H
|
||||
#define WEECHAT_TEST_UNIT_CORE_H
|
||||
|
||||
#define DATA_HASH "this is a test of hash function"
|
||||
#define DATA_HASH_CRC32 "ef26fe3e"
|
||||
#define DATA_HASH_MD5 "1197d121af621ac6a63cb8ef6b5dfa30"
|
||||
#define DATA_HASH_SHA1 "799d818061175b400dc5aaeb14b8d32cdef32ff0"
|
||||
#define DATA_HASH_SHA224 "637d21f3ba3f4e9fa9fb889dc990b31a658cb37b4aefb5144" \
|
||||
"70b016d"
|
||||
#define DATA_HASH_SHA256 "b9a4c3393dfac4330736684510378851e581c68add8eca841" \
|
||||
"10c31a33e694676"
|
||||
#define DATA_HASH_SHA384 "42853280be9b8409eed265f272bd580e2fbd448b7c7e236c7" \
|
||||
"f37dafec7906d51d982dc84ec70a4733eca49d86ac19455"
|
||||
#define DATA_HASH_SHA512 "4469190d4e0d1fdc0afb6f408d9873c89b8ce89cc4db79fe0" \
|
||||
"58255c55ad6821fa5e9bb068f9e578c8ae7cc825d85ff99c439d59e439bc589d95620a" \
|
||||
"1e6b8ae6e"
|
||||
#define DATA_HASH_SHA3_224 "26432a3a4ea998790be43386b1de417f88be43146a4af98" \
|
||||
"2a9627d10"
|
||||
#define DATA_HASH_SHA3_256 "226e3830306711cf653c1661765c304b37038e7457c35dd" \
|
||||
"14fca0f6a8ba1d2e3"
|
||||
#define DATA_HASH_SHA3_384 "77bc16f89c102efc783ddeccc71862fe919b66e1aaa88bd" \
|
||||
"2ba5f0bbe604fcb86c68f0e401d5d553597366cdd400595ba"
|
||||
#define DATA_HASH_SHA3_512 "31dfb5fc8f30ac7007acddc4fce562d408706833d0d2af2" \
|
||||
"e5f61a179099592927ff7d100e278406c7f98d42575001e26e153b135c21f7ef5b00c8" \
|
||||
"cef93ca048d"
|
||||
#define DATA_HASH_SALT "this is a salt of 32 bytes xxxxx"
|
||||
#define DATA_HASH_PBKDF2_SHA1_1000 "85ce23c8873830df8f0a96aa82ae7d7635dad12" \
|
||||
"7"
|
||||
#define DATA_HASH_PBKDF2_SHA1_100000 "f2c2a079007523df3a5a5c7b578073dff06ba" \
|
||||
"49f"
|
||||
#define DATA_HASH_PBKDF2_SHA256_1000 "0eb0a795537a8c37a2d7d7e50a076e07c9a8e" \
|
||||
"e9aa281669381af99fad198997c"
|
||||
#define DATA_HASH_PBKDF2_SHA256_100000 "b243ef60f9d9e7a6315f874053802cfb3b7" \
|
||||
"b5a3502d47cf7fd76b3ee5661fcff"
|
||||
#define DATA_HASH_PBKDF2_SHA512_1000 "03d8e9e86f3bbe20b88a600a5aa15f8cfbee0" \
|
||||
"a402af301e1714c25467a32489c773c71eddf5aa39f42823ecc54c9e9b015517b5f3c0" \
|
||||
"19bae9463a2d8fe527882"
|
||||
#define DATA_HASH_PBKDF2_SHA512_100000 "286cca5521b00a7398530fbf11a570401a8" \
|
||||
"0c901f1584cb493fcb75c49e5c30613c331ce318b34615a08be2fdcb9a3b4d3e9a5b62" \
|
||||
"e119db6941010533cdf73d3"
|
||||
|
||||
#endif /* WEECHAT_TEST_UNIT_CORE_H */
|
Loading…
Reference in New Issue