From 31c235f145189fe146f9374d6826927de5964a07 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 24 Nov 2024 08:16:43 +0100
Subject: Include entropy (expressed in bits or bytes) into the Python API.

---
 plugins/pychrysalide/common/Makefile.am |   1 +
 plugins/pychrysalide/common/entropy.c   | 119 ++++++++++++++++++++++++++++++++
 plugins/pychrysalide/common/entropy.h   |  39 +++++++++++
 plugins/pychrysalide/common/module.c    |   2 +
 plugins/pychrysalide/common/xdg.c       |   1 -
 src/common/entropy.c                    |  12 +++-
 src/common/entropy.h                    |   5 +-
 7 files changed, 174 insertions(+), 5 deletions(-)
 create mode 100644 plugins/pychrysalide/common/entropy.c
 create mode 100644 plugins/pychrysalide/common/entropy.h

diff --git a/plugins/pychrysalide/common/Makefile.am b/plugins/pychrysalide/common/Makefile.am
index cc87a82..43e1fc4 100644
--- a/plugins/pychrysalide/common/Makefile.am
+++ b/plugins/pychrysalide/common/Makefile.am
@@ -14,6 +14,7 @@ noinst_LTLIBRARIES = libpychrysacommon.la
 
 libpychrysacommon_la_SOURCES =				\
 	bits.h bits.c							\
+	entropy.h entropy.c						\
 	module.h module.c						\
 	xdg.h xdg.c
 
diff --git a/plugins/pychrysalide/common/entropy.c b/plugins/pychrysalide/common/entropy.c
new file mode 100644
index 0000000..2817747
--- /dev/null
+++ b/plugins/pychrysalide/common/entropy.c
@@ -0,0 +1,119 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * entropy.c - équivalent Python du fichier "common/entropy.c"
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "entropy.h"
+
+
+#include <common/entropy.h>
+
+
+#include "../access.h"
+#include "../helpers.h"
+
+
+
+/* Détermine l'entropie d'un contenu binaire. */
+static PyObject *py_entropy_compute_entropy(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = NULL car méthode statique.                            *
+*                args = arguments fournis lors de l'appel à la fonction.      *
+*                                                                             *
+*  Description : Détermine l'entropie d'un contenu binaire.                   *
+*                                                                             *
+*  Retour      : Valeur d'entropie du contenu fourni.                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_entropy_compute_entropy(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    const bin_t *data;                      /* Données à traiter           */
+    int bits;                               /* Choix de référentiel        */
+    size_t len;                             /* Quantité de ces données     */
+    int ret;                                /* Bilan de lecture des args.  */
+    double entropy;                         /* Valeur d'entropie déterminée*/
+
+#define COMPUTE_ENTROPY_METHOD PYTHON_METHOD_DEF        \
+(                                                       \
+    compute_entropy, "data, /, bits=False",             \
+    METH_VARARGS, py_entropy,                           \
+    "Compute the entropy of provided data.\n"           \
+    "\n"                                                \
+    "The *data* to process can be a string or bytes."   \
+    " The optional *bits* argument defines if the"      \
+    " computed value is expressed in bits (log base 2)" \
+    " or in bytes (log base 256).\n"                    \
+    "\n"                                                \
+    "The result is a float value."                      \
+)
+
+    bits = 0;
+
+    ret = PyArg_ParseTuple(args, "s#|p", &data, &len, &bits);
+    if (!ret) return NULL;
+
+    entropy = compute_entropy((const bin_t *)data, len, bits);
+
+    result = PyFloat_FromDouble(entropy);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Définit une extension du module 'common' à compléter.        *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool populate_common_module_with_entropy(void)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *module;                       /* Module à recompléter        */
+
+    static PyMethodDef py_entropy_methods[] = {
+        COMPUTE_ENTROPY_METHOD,
+        { NULL }
+    };
+
+    module = get_access_to_python_module("pychrysalide.common");
+
+    result = register_python_module_methods(module, py_entropy_methods);
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/common/entropy.h b/plugins/pychrysalide/common/entropy.h
new file mode 100644
index 0000000..3fe5e28
--- /dev/null
+++ b/plugins/pychrysalide/common/entropy.h
@@ -0,0 +1,39 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * entropy.h - prototypes pour l'équivalent Python du fichier "common/entropy.c"
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_COMMON_ENTROPY_H
+#define _PLUGINS_PYCHRYSALIDE_COMMON_ENTROPY_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/*  Définit une extension du module 'common' à compléter. */
+bool populate_common_module_with_entropy(void);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_COMMON_ENTROPY_H */
diff --git a/plugins/pychrysalide/common/module.c b/plugins/pychrysalide/common/module.c
index 7af12ba..fa2b4de 100644
--- a/plugins/pychrysalide/common/module.c
+++ b/plugins/pychrysalide/common/module.c
@@ -26,6 +26,7 @@
 
 
 #include "bits.h"
+#include "entropy.h"
 //#include "fnv1a.h"
 //#include "hex.h"
 //#include "itoa.h"
@@ -107,6 +108,7 @@ bool populate_common_module(void)
     if (result) result = populate_common_module_with_pathname();
     if (result) result = populate_common_module_with_pearson();
     */
+    if (result) result = populate_common_module_with_entropy();
     if (result) result = populate_common_module_with_xdg();
 
     if (result) result = ensure_python_bitfield_is_registered();
diff --git a/plugins/pychrysalide/common/xdg.c b/plugins/pychrysalide/common/xdg.c
index 789a0a6..e4b269e 100644
--- a/plugins/pychrysalide/common/xdg.c
+++ b/plugins/pychrysalide/common/xdg.c
@@ -26,7 +26,6 @@
 
 
 #include <malloc.h>
-#include <pygobject.h>
 
 
 #include <common/xdg.h>
diff --git a/src/common/entropy.c b/src/common/entropy.c
index 1f3adfa..8dae698 100644
--- a/src/common/entropy.c
+++ b/src/common/entropy.c
@@ -33,6 +33,7 @@
 *                                                                             *
 *  Paramètres  : data = séquence d'octets à traiter.                          *
 *                len  = quantité de ces octets.                               *
+*                bits = calcul en concidérant les bits et non les octets ?    *
 *                                                                             *
 *  Description : Détermine l'entropie d'un contenu binaire.                   *
 *                                                                             *
@@ -42,13 +43,13 @@
 *                                                                             *
 ******************************************************************************/
 
-double compute_entropy(const bin_t *data, size_t len)
+double compute_entropy(const bin_t *data, size_t len, bool bits)
 {
     double result;                          /* Valeur calculée à renvoyer  */
     unsigned long counters[256];            /* Décompte des valeurs        */
     const bin_t *d_max;                     /* Borne de fin de parcours #1 */
     const bin_t *d_iter;                    /* Boucle de parcours #1       */
-    double log_2;
+    double log_2;                           /* Valeur constante de log2    */
     unsigned long *c_max;                   /* Borne de fin de parcours #2 */
     unsigned long *c_iter;                  /* Boucle de parcours #2       */
     double freq;                            /* Fréquence liée à une valeur */
@@ -62,7 +63,12 @@ double compute_entropy(const bin_t *data, size_t len)
     for (d_iter = data; d_iter < d_max; d_iter++)
         counters[*d_iter]++;
 
-    log_2 = log(256.0);
+    /**
+     * Explication du choix de log :
+     * https://stackoverflow.com/questions/990477/how-to-calculate-the-entropy-of-a-file/990646#990646
+     */
+
+    log_2 = log(bits ? 2.0 : 256.0);
 
     c_max = counters + 256;
 
diff --git a/src/common/entropy.h b/src/common/entropy.h
index f747149..b677a77 100644
--- a/src/common/entropy.h
+++ b/src/common/entropy.h
@@ -25,12 +25,15 @@
 #define _COMMON_ENTROPY_H
 
 
+#include <stdbool.h>
+
+
 #include "../arch/archbase.h"
 
 
 
 /* Détermine l'entropie d'un contenu binaire. */
-double compute_entropy(const bin_t *, size_t);
+double compute_entropy(const bin_t *, size_t, bool);
 
 
 
-- 
cgit v0.11.2-87-g4458