Vous consultez une page technique concernant le logiciel de gestion Mercator. Celle-ci contient des informations spécifiques destinées aux professionnels de Mercator. Souhaitez-vous être redirigés vers des informations plus générales ?


   Ne plus poser cette question

Protéger des fichiers stockés dans la base de données contenant des informations sensibles

0000003089     -      24/06/2022

Mercator 10.10 ou ultérieur permet d'apporter une protection supplémentaire à des fichiers stockés dans la base de données SQL et contenant des données sensibles. Par exemple, des informations produits confidentielles, des scans de carte d'identité, des relevés d'identité bancaire, ... Cette protection est réalisée sous la forme d'un encryptage dans la base de données SQL. Ces fichiers deviennent alors uniquement lisibles dans Mercator et, pour autant que ce Mercator fonctionne sur un poste disposant du certificat ayant servi au cryptage. 
En résumé, ces fichiers

  • depuis un Mercator sans ce certificat, sont illisibles
  • depuis un autre programme que Mercator, sont illisibles (par exemple, les outils clients de SQL Server)
  • depuis un autre programme que Mercator, avec ce certificat sur le poste, sont toujours illisibles
  • depuis Mercator avec le certificat adéquat, sont lisibles
  • depuis une application externe ayant instancié MercatorUi.Main, sur un poste/serveur disposant du certificat, et utilisant les outils de Mercator (Api.Zselect), sont lisibles.

Le cryptage et le décryptage sont effectués par Mercator. Il ne faut dès lors rien changer dans le paramétrage ou la programmation sur mesure autour de Mercator, hormis si des sauvegardes de fichiers sont effectuées en direct dans la base de données.

Contrairement aux colonnes cryptées, il n'y a pas de procédure de cryptage de tous les fichiers existants (opération trop coûteuse). En conséquence, des fichiers cryptés peuvent côtoyer des fichiers non cryptés.

Dans un explorateur de fichiers SQL (SqlFileView), les  fichiers cryptés se reconnaissent grâce à ce petit cadenas :

 

Installation du certificat : voir cette page.

Une fois un fichier crypté dans la base de données, l'option "Autres / Empreinte certificat cryptage données" (id = CERT_THUMB) n'est plus modifiable.

 

Crypter un fichier existant

Le cryptage d'un fichier existant s'effectue via un clic-droit sur ce fichier. Après confirmation, le cryptage est effectué immédiatement et ne provoquera pas de demande de sauvegarde.

Il est possible de crypter plusieurs fichiers simultanément en les sélectionnant au préalable. Les fichiers déjà cryptés sont automatiquement exclus de la sélection.

 

Cryptage lors de la sauvegarde

L'explorateur de fichiers SQL présente cette case à cocher qui permet de déterminer si un fichier ajouté à l'explorateur de fichiers SQL doit être crypté lors de la sauvegarde ou pas.

 

Par défaut, cette case n'est pas cochée. Il est toutefois possible de changer ce comportement en fixant la propriété Encryption de l'objet SqlFileView en mode paramétrage d'écran :

  • Never : cette case est décochée et non modifiable
  • Alwayscette case est cochée et non modifiable
  • InitiallyUncheckedcette case est décochée et modifiable
  • InitiallyChecked : cette case est cochée et modifiable.

 

Crypter par programmation

Le code ci-dessous montre comment crypter par code toute une série de fichiers SQL (ceux associés à la séquence ACH). Il faut prendre en compte le fait que le cryptage de fichiers est une opération consommatrice de CPU et de mémoire vive. Il est vraisemblable qu'un tel processus requiert un temps d'exécution important.

Cet exemple pose l'hypothèse que l'exécution du code est effectuée dans Mercator. En conséquence, le certificat et sa clé publique sont disponibles. Si tel n'est pas le cas, il est nécessaire de disposer de la clé publique du certificat, de charger cette version du certificat (certificat sans clé privée) et d'adapter le code comme dans le second exemple dans le bas de cette page (utilisation de la signature de MercatorEncryptRsaAes permettant de passer le paramètre certificate:)

 

Zoom
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using MercatorApi;
using MercatorExtensions;
using MercatorUi;
using MercatorDatabase;

// <CompileWithRoslyn />

namespace MyNameSpace
{
    public class Class1 : MercatorUi.Interfaces.IExec
    {

        public void Main()
        {
            DataSet ds = Api.Zselect(MercatorUi.Globals.RepData, @"select id,filecontent from FILES where (filepath like '<Files\ACH\%') and (filecontent is not null) and (DATALENGTH(filecontent) > 0) and (dbo.IS_BINARY_MERCATORENCRYPTED(filecontent)=0)");
            if (ds == null)
                return;
            int nok = 0;
            int nko = 0;
            using (MercatorSqlConnection conn = new MercatorSqlConnection(MercatorUi.Globals.RepData, true))
            {
                if (conn.Connection == null)
                    return;
                Api.IsWeb = true; // ne pas avoir de message d'erreur si Api.SqlExec renvoie false
                try
                {
                    MercatorUi.Progress.ProgressCreate(ds.Tables[0].Rows.Count);
                    using (SqlCommand cmd = new SqlCommand("update FILES set filecontent=@filecontent where id=@id", conn.Connection))
                    {
                        foreach (DataRow dr in ds.Tables[0].Rows)
                        {
                            MercatorUi.Progress.ProgressCreate(1);
                            cmd.Parameters.AddWithValue("@id", dr["id"]); //guid -> uniqueidentifier
                            cmd.Parameters.AddWithValue("@filecontent", MercatorCryptorEngine.CryptorEngine.MercatorEncryptRsaAes((byte[])dr["filecontent"]));
                            if (Api.SqlExec(cmd))
                                nok++;
                            else
                                nko++;
                            cmd.Parameters.Clear();
                        }
                    }
                    MercatorUi.Progress.ProgressDestroy();
                }
                finally
                {
                    Api.IsWeb = false;
                }
            }
            Dialogs.Stop($"Fichiers correctement cryptés : {nok}.\r\nFichiers non cryptés : {nko}.");
        }
    }
}