Est-il possible de protéger par mot de passe une base de données en utilisant sqlite3 avec python?
Version imprimable
Est-il possible de protéger par mot de passe une base de données en utilisant sqlite3 avec python?
Bonjour.
Oui.
Bonjour aussi.
J'ai participé à une discussion ici en 2014, et ma réponse n'a pas changée:
https://www.developpez.net/forums/d1...nees-cryptees/
Pour le cryptage: tout est possible, y compris RSA, mais ça dépend de l'importance des données (conséquences d'une divulgation?). Pour des données d'importance modérée, un cryptage "xor" devrait être suffisant.
Il reste que la base est non-cryptée pendant l'exécution du programme. A voir possibilité si la base est petite à l'utiliser décryptée uniquement en mémoire (disque virtuel?) avec précautions en cas de coupure de courant.
Salut,
Ce serait une fonctionnalité de sqlite3 (et vous pouvez fabriquer votre mouture de sqlite3 pour...) (mais cette extension n'est pas dans le sqlite3 livré avec Python).
sqlite3 est plutôt orienté base de données "embarquée".
Si on veut se protéger ce sera contre le vol du disque, du PC, ... qui contient le fichier de la base de données.
Le chiffrement du disque, le mot de passe que l'utilisateur entre lorsqu'il se connecte sont des protections "générales" disponibles.
Les SGDB plus génériques sont plus protégées "de base" et des extensions pour le chiffrement (si on veut se protéger contre les administrateurs du système qui héberge la base de données...)
- W
Merci à tous
J'essaierai toutes les méthodes mentionnées, mais l'utilisation du cryptage affecte-t-elle les performances de la base de données en termes de vitesse de lecture et d'écriture?
Fatalement oui, tout calcul sur une donnée avant de l'écrire est toujours plus long qu'écrire la donnée sans la modifier.
Mais t'as pas bien pigé l'idée: l'idée n'est pas de chiffrer (c'est le terme exact) la bdd en temps réel, c'est
- la déchiffrer au début du programme, déchiffrement générant une bdd "prime" qui sera soit sur disque, soit en RAM
- travailler sur la bdd "prime" non chiffrée
- la chiffrer quand on quitte le programme (ou à intervalles fixes ou sur demande éventuellement) et effacer la bdd "prime"
Les opérations se faisant sur une bdd non chiffrée seront donc des opérations classiques, aussi rapides que les autres. C'est la phase déchiffrement du début et chiffrement final qui seront plus ou moins longues, mais faites une seule fois donc négligeables.
Pour rester simple est-il possible utiliser DB Browser for SQLite pour créé une mot de passe
Pièce jointe 592302
Bonjour,
Je ne connais pas DB Browser, mais il s'agit d'un éditeur de base de données sqlite comme il en existe d'autres, payants ou pas. J'utilisais beaucoup il y a quelques années "SQLite Expert pro" (http://www.sqliteexpert.com/) version payante (une centaine d'euros pour une licence), mais il existe une version gratuite plus légère. Cependant, je n'ai pas vu de fonctionnalités de cryptage.
Pour DB Browser, il y a des infos sur le cryptage des bases de données ici:
https://github.com/sqlitebrowser/sql...pted-Databases
Mais ce logiciel n'a rien à voir avec Python, et s'il fait un cryptage AES, tu auras du mal à lire ta base de données avec Python (il faudra décrypter avant et recrypter après, le tout en AES). Ce n'est cependant pas impossible, mais tu te prépares des moments difficiles...
Si tu veux rester simple, il te faudra choisir entre Python OU ce logiciel pour gérer ta base de données sqlite...
Pour la version Python, et dans la mesure où tes données ne sont pas de niveau "sécurité défense", je te propose un cryptage XOR avec clé. Il est déjà assez fort, assez difficile à décrypter, facile à coder en Python, et d'exécution rapide.
Voilà un petit code qui fait ça:
Comme les octets font l'objet d'un xor ("ou exclusif" => opérateur '^') avec une clé qui sert de mot de passe, il sera difficile à un pirate de retrouver le message grâce à la reconnaissance d'une fréquence de lettres. Mais il ne faudra pas oublier la clé! A noter une particularité du cryptage xor: pour décrypter, on utilise la fonction de cryptage une seconde fois!Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Cryptage xor avec clé d'un texte et d'un fichier """ ############################################################################### def cryptxortexte(btexte, bkey): """Cryptage xor avec clé d'un texte Attention: btexte et bkey doivent être de type "bytes" et retourne le texte crypté de type bytes """ lgkey = len(bkey) encoded = [] for i in range(0, len(btexte)): encoded.append(btexte[i] ^ bkey[i % lgkey]) return bytes(encoded) ############################################################################### def cryptxorfichier(fichier1, fichier2, key, tbuf=8192): """Cryptage xor avec clé d'un fichier1 => fichier2 fichier2 doit être différent de fichier1 key est la clé de cryptage (type str ou bytes) tbuf la taille du buffer de lecture des données du fichier1 """ if isinstance(key, str): key = bytes(key, "utf-8") lgkey = len(key) tbuf2 = tbuf//lgkey*lgkey # buffer qui contient un nombre entier de key with open(fichier1, "rb") as fs: with open(fichier2, "wb") as fd: while True: buf = fs.read(tbuf2) if len(buf)==0: break fd.write(cryptxortexte(buf, key))
Deux petites précautions à prendre:
- Évite de coder en clair la clé dans ton code!
- Si ton programme crashe, la base de données ne sera pas cryptée. Il faudra donc qu'au lancement, ton programme puisse tester si ta base de données est cryptée ou pas, pour en déduire ce qu'il doit faire!
Si tu veux un cryptage plus fort, il existe des modules Python externes qui font ça (voir déjà pypi: https://pypi.org/).
J’espère que la protection de tes données mérite les précautions que tu veux prendre...
Merci Tirtamos pour l'exemple de crypyage / décryptage. Bien sûr, on ne peut pas mettre la clé en clair dans le code source. Pour la faire intervenir dans une fonction, j'ai songé à la stocker dans un fichier ou une base de données. Mais ceux-ci sont eux-mêmes susceptibles d'être violés. Plus généralement, un module python, qui est public, pour le cryptage, comment fait-il pour crypter sans livrer ses secrets ?
Merci wiztricks. J'ai révisé cette notion. Mais le problème demeure, il me semble : comment garder la clé privée secrète ?
bonjour
Tu parles de la variable str key passée en paramètre dans l'exemple ? Il n'y a pas de solution particulière. Tout dépend du contexte.
Elle peut parfois être passée au programme via une variable d'environnement
Parfois, dans le fichier config de l'application (ou d'un utilisateur). Elle peut être dans un fichier (texte en clair) mais pas accessible à tout le monde
Merci papajoker et Sve@r. Mon problème est que toute l'application est visible dans un repository Github. Une constante dans le code source, une info dans un fichier texte, un fichier config, tout. Peut-être la base de données (sqlite3) n'est-elle pas lisible en clair, je ne sais pas (je suis pas pro du tout !). Mais je suppose que ce ne doit pas être difficile. Alors il faut crypter ce mot de passe. Mais si j'ai bien compris le principe du chiffrement asymétrique, après avoir codé et stocké le mot de passe, il faut conserver la clé privée, pour le décrypter quand on le communiquera à la fonction qui envoie le mail. Et c'est là que le fait qu'on soit en open source me pose problème.
La variable d'environnement, je connais pas, il faut que je potasse ça. Pour l'instant, le seul rapport que j'ai eu avec cette notion, c'est que le port du serveur Bottle, là où j'héberge, en est une.
Bonjour
Ce problème de clé qu'on doit cacher, pour crypter / décrypter le fichier sqlite3, n'est pas facile à résoudre. Il y a cependant des solutions.
La 1ère me semble être de la demander à l'utilisateur! Mais, bien sûr, il faut la tester avant de l'utiliser. Et on ne peut pas la comparer à la clé mise en clair dans le code source. Par contre, on peut la crypter avec un algorithme de type sha256 (module hashlib), et la comparer avec la bonne clé elle-même cryptée avec le même algorithme et placée dans le code source. En effet, ce genre d'algorithme n'a pas de possibilité de décryptage, et donc, la connaissance de la clé cryptée ne permet pas de connaître la clé d'origine. C'est la méthode utilisée pour vérifier des mots de passe.
Pour les autres solutions, il ne faut pas diffuser le code source Python, mais le code Python compilé pour rendre plus compliqué de retrouver la méthode choisie. Bien sûr, on peut toujours "décompiler", mais ce n'est plus à la portée de n'importe qui... On peut compiler en utilisant par exemple cx_freeze ou pyinstaller (=> ".exe" sous Windows). Il s'agit d'une compilation en codes intermédiaires dont le résultat sera utilisable directement par l'interpréteur Python.
Pour avoir une bonne clé de cryptage/décryptage sans la donner, il y a une solution très inhabituelle: certains algorithmes de génération de nombres pseudo-aléatoires génèrent toujours la même suite de nombres. On peut donc les utiliser pour générer la clé sans la donner! Mais il ne faut pas utiliser random qui serait trop facile à trouver par une décompilation. Par exemple, un algorithme de type Fibonacci (voir ici: http://lwh.free.fr/pages/algo/crypto/prng.html) est facile à programmer:
Au lieu de lui faire générer des chiffres, on pourrait lui faire générer des nombres, des octets, des lettres, etc...Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 def genfiboalea(x0, x1, nb): """Génère nb chiffres pseudo-aléatoires (méthode de fibonacci) x0 et x1: graines de départ pour la génération """ M = 10 for i in range(0, nb): xn = (x0+x1) % M x0 = x1 x1 = xn yield xn alea = genfiboalea(3, 7, 10) for x in alea: print(x) 0 7 7 4 1 5 6 1 7 8
Il faut bien sûr 2 graines (x0 et x1) pour initialiser l'algorithme (ici 3 et 7), mais la relation entre ces graines et la clé à trouver nécessite de comprendre l'algorithme avec la dé-compilation. Si on veut avoir un algorithme plus compliqué, on peut toujours. Par exemple le "Blum Blum Shub" (https://fr.wikipedia.org/wiki/Blum_Blum_Shub). Cet algorithme est très bon puisqu'il est accepté comme "cryptographiquement sûr". J'avais fait une petite étude sur le sujet (https://python.jpvweb.com/python/mes...id=genalea_bbs), mais il faut un certain courage pour se lancer là-dedans ! :D
Compris.
Déjà pour ta question annexe, une bdd sqlite est totalement lisible. Il existe un tas de lecteurs/navigateurs sqlite gratuits dont le premier "sqlitebrowser" est directement offert sous Debian (et dérivées telle Ubuntu). Suffit de taper la commande apt install sqlitebrowser. Et beaucoup d'outils utilisent sqlite sans se cacher (ni cacher les données). Par exemple le navigateur firefox stocke les mots de passe (quand tu fais "conserver le mot de passe" d'un site) dans un fichier sqlite nommé "key4.db" totalement ouvert.
Donc ça ne répond pas vraiment à la question "secrète vis à vis de qui".
Exemple: ton utilisateur peut utiliser ce programme (opensource) librement et gratuitement, tu n'as donc pas besoin que les données soient secrètes vis à vis de lui. Ce qui est nécessaire c'est que ses données à lui soient secrètes vis à vis d'un autre utilisateur qui utiliserait ton même programme dans son coin à lui. Dans ce cas, à l'initialisation du programme, tu génères le couple clef privée/cléf publique, tu stockes la clef privée dans un fichier local de l'utilisateur (à l'instar de ssh qui stocke les clefs privées de l'utilisateur dans un dossier ".ssh" verrouillé) et tu chiffres la bdd. Ensuite, dans l'utilisation habituelle, le programme ayant accès à la clef privée peut alors déchiffrer la bdd avant de l'utiliser.
Au fait, les termes exacts ne sont pas "cryptage/décryptage' mais "chiffrement/déchiffrement" car le terme "décryptage" fait référence à l'attaquant qui veut casser un code dont il n'est pas le propriétaire et dont il n'a pas la clef ; et par opposition le terme "cryptage" devrait faire référence à l'attaquant qui veut créer un code sans avoir la clef, ce qui est débile.
Autre exemple: tu ne te préoccupes absolument pas de la confidentialité de ta bdd (es-tu réellement obligé?). Donc ta bdd est libre et ouverte et lisible et l'utilisateur qui utilise ton programme en a pleinement conscience.
Toutefois l'utilisateur lui peut s'il en a envie, chiffrer cette bdd avec des outils divers. Par exemple VeraCrypt. Son principe est extrèmement simple
- tu crées un container (un disque dur virtuel) chiffré
- quand tu veux y accéder, tu tapes le mot de passe => le disque dur est alors monté sur ton système comme s'il s'agissait d'une clef USB ou d'un CDROM
- tu accèdes librement à ton disque dur, tu y déposes des fichiers, tu en récupères, exactement comme tu fais avec une clef USB. Les fichiers déposés sont chiffrés à l'écriture, les fichiers récupérés sont déchiffrés à la lecture et de façon transparente pour toi
- quand tu as fini, tu démontes ton disque et tout redevient inaccessible
L'utilisateur pourra donc utiliser ce même principe pour, s'il en a envie, cacher sa bdd aux autres. Quand il veut utiliser ton programme il monte le disque, et quand il a fini il le démonte.
Comme tu vois, la question "secrète vis à vis de qui" avait vraiment toute son importance...
En plus ce logiciel VeraCrypt peut (et je trouve ça génial) créer (si on le désire) deux disques chiffrés par volume. Le premier, servant de leurre, ne contenant que des fichiers bidons, et l'autre, le vrai, caché dans le premier et contenant les fichiers vraiment sensibles. Mais rien ne peut prouver qu'un volume veracrypt contient un ou deux disques (déni plausible)...
Énormément de projets open sources utilisent la notion de clé de chiffrement, simplement elle n'est pas dans le code
Elle est donc définie au déploiement de l'application (et dev)
Tu sembles parler d'une application web serveur...
- gitea : SECRET_KEY dans fichier de config non accessible depuis le web
- django : SECRET_KEY est généralement une variable d'environnement (au moins en cours de développement)
setting.py SECRET_KEY = os.getenv('DJANGO_SECRET_KEY') Ensuite, chacun peut changer cette ligne et lire la clé depuis un fichier...
- voir wordpress et bien d'autres...
Et puisque l'on utilise principalement docker pour distribuer un serveur web python, on place cette variable d'environnement dans la config docker
ps: même chose pour le mot de passe admin de notre BD, il est simplement (en clair) dans une variable d'environnement (ou fichier externe .env non dans le dépôt git)
Et si on ne parles pas de serveur, si la clé est dans un fichier texte dans un répertoire de l'utilisateur, elle ne peut-être lue que par l'utilisateur (et est unique pour chaque utilisateur: a faire à l'install)
Donc en résumé : cette "clé" est générée uniquement à l'installation (il est donc normal de ne pas l'avoir en statique sur un dépot git) et est unique à chaque installation
Merci à tous, pour vos infos riches ! Je précise que je me suis pas mis sur Github pour distribuer mon appli, parce qu'elle est loin d'être au point ! Le fait de montrer mon code est autant égoïste qu'altruiste. Si j'ai eu des bonnes idées, qu'elles puissent profiter à d'autres, mais si je fais des c...., on peut me les montrer ! (D'ailleurs, c'est ce qui s'est passé. Bien avant de songer à mettre l'appli en open, j'avais le mot de passe pour l'authentification des mails auto en dur dans le code. Et j'ai oublié ! Résultat, 600 mails pourris envoyés par moi ! " I have bad news. I have pirated your device, You must pay me x$, voilà mon bitcoin") . Probablement quelqu'un désireux de m'alerter ! Ça a bien marché.
En fait, il se trouve que j'ai été intéressé par l'offre de scalingo d'un essai d'un mois gratuit, et qu'ils fonctionnent avec Github.
Donc, la question des utilisateurs éventuels de mon code n'est pas encore posée, à mon avis. Pour l'instant, je considère qu'il y a un seul utilisateur, moi, qui dois essuyer les plâtres. De plus, il n'y a pas forcément là un produit commercial.
Voici d'ailleurs les liens, de l'appli elle-même avec une url provisoiore, et du repository Github.
https://vaste-programme.osc-fr1.scalingo.io/
https://github.com/Zakod/librerie
petit HS (marketing) sur ton dépôt git
Pour faire de l'open source, il faut appâter le chaland (collaborateur) et ici rien n'est fait...
- bottle ? pourquoi utiliser un truc pas standard ? flask me parait proche au niveau code et tout dev web python connait flask (voir django). Si un dev web sur 500 connait bottle, c'est déjà diviser d'office par 500 le nombre de collaborations potentiels...
- le style ! parfois des tabulations ! pour éviter les PR a répétition sur chaque ligne pour un simple espace, voir pep 8...257. Perso, avec un style totalement "libre" je fuis car cela me donne tout de suite une très mauvaise image du développeur (et m'assure d'avoir plus tard des PR compliqués)
- bottle : pourquoi utiliser avec une grosse parcimonie les templates ? ! En serveur web, le seul modèle bien reconnu est MVC et ici rien pour les datas (comme le style, cela fait immédiatement fuir)
Donc, pour moi,
- le style et MVC et un minimum
- les tests ! c'est un must : ici on dit clairement aux autres développeurs que l'on est une personne sérieuse (peut l'être sans)
-------
Et savoir utiliser, comprendre un minimum git est une nécessité : ici, on ressent très bien la personne qui utilise git pour la première fois... (commits: delete fichier, commit le même fichier, delete même fichier, .... ) du coup on n'utilise même plus git, mais on l'utilise comme un simple ftp
Il est vrai que je suis novice. Pas pro, comme je l'ai dit. Candide, quoi ! Et comme je l'ai dit, j'ai déposé mon code parce que scalingo m'y encourageait. Donc, c'est vrai, je ne cherche pas forcément le "chaland". Mais le fait qu'on puisse me donner des conseils, comme là, est très utile. J'utilise Bottle parce que c'est archi simple, donc idéal pour un novice. Mais je songe éventuellement à me mettre à plus courant. Avant cela, je vais aboutir ce projet dans ces conditions, et je ne migrerai vers un autre framework que si le succès de mon blog m'y oblige (je me fais du souci avec le fait que c'est mono-thread. Mais d'après ce que j'ai lu, on peut adosser un programme Bottle sur un serveur sérieux. Si le succès du blog fait que ça rame, là je changerai, soit en adossant sur Apache, soit en traduisant en Django. J'ai vu qu'il y avait un cours sérieux sur OC.
Qu'est-ce que tu appelles le style ? Par exemple le fait que je cause pas anglais ? Là encore, il faut comprendre le paradoxe de ma mise en open à moi ! Scalingo me l'a demandé, et j'ai trouvé que c'était bien d'avoir des conseils (d'ailleurs, je suis servi !). Je ne cherche pas forcément de collaborateurs. Mais songe qu'avec un novice qui mérite autant de reproches, il faut être plus pédagogique ! Par exemple, je pige pas ce que c'est que les PR.
"parfois des tabulations ! pour éviter les PR a répétition sur chaque ligne pour un simple espace"
Je pige pas de quoi tu parles ! Moi, il faut partir de zéro ! Est-ce que tu parles de ma fonction tabul ? C'est pour que le code html soit bien lisible. Sans elle, y avait aucune indentation, trouver un bug c'était mission impossible. Tout a été réglé avec. Toutes mes pages html sont écrites automatiquement, avec un programme de saisie du texte et des images qui est indépendant (en gros, tout ce qui est dans le dossier html avec des noms en clairs), et par l'appli elle-même (formulaires, et textes postés par les visiteurs, avec un nom aléatoire, je crois qu'il n'y en a pas pour l'instant, j'ai viré tous les essais que j'avais faits.)
J'utilise très peu de templates, il est vrai. D'une part ça porte à zéro à peu près le temps d'écriture de code html, et d'autre part, toujours pareil, je connais pas tout. Par exemple, Y a une fonction Template() dont je me sers pas, vu que j'en ai pas besoin. J'en suis resté aux premiers tutos que j'ai trouvés, et j'ai eu fort à faire pour venir à bout du cahier des charges que j'avais adopté.
Merci pour ton intérêt, et tes conseils, mais adapte-les à mon niveau, que je les comprenne ! Tu parles de mauvaise image, c'est juste un niveau d'amateur. Je suis amateur. Ça veut pas seulement dire que mon niveau est pas top, ça veut aussi dire que j'aime, que j'adore ça. Que je programme pour mon plaisir, en plus de l'utilité. Je bosse sans impératif de rentabilité. J'adore pondre un algo en réponse à tel ou tel besoin, au point même que des fois, je programme ce qui existe peut-être déjà !
Pour résumer : il faut être pédago et patient avec moi ! Et je suis preneur de reproches quand je les comprends ! Et faut accepter mon "style", puisque de toute façon, je ne cherche pas à recruter du monde.
PS : j'ai résolu le principal problème évoqué dans ce fil, en incluant le mot de passe dans un fichier .env, sur tes conseils ! Je dois demain inaugurer le gitignore pour y placer ce fichier .env, ainsi que la base de données elle-même, et aussi un journal auquel je ne pensais plus, mais qui lui aussi ne doit pas être exposé. Et j'ai haché les mots de passe utilisateur.
Qu'est-ce qu'on est bavard sur ce fil !
Bonne soirée, et encore merci.
Il n'y a aucun reproches :D, j'ai été aussi un débutant. Je n'ai parlé que de marketing open source : Si on désire un partage avec d'autres devs
style
C'est uniquement la présentation du code
pour un code perso, pas forcément utile, mais pour un travail en groupe (société, club, opensource), on doit tous adopter le même style/présentation pour faciliter la lecture aux autres.
j'ai donné 2 références pep 8 (original) et pep 257 (fortement conseillé mais pas obligatoire). Existe des outils (intégrés dans les éditeurs spécifiques à python: black,autopep8,...) pour nous rappeler les règles, voir-même formater automatiquement notre code suivant ces règles.
Mon exemple était: utiliser parfois des espaces et parfois des tabulations pour faire des indentations (block: if, for, def...)
PR
c'est Pull Request : un autre développeur envoi une modification à ton dépôt git (modification qui peut-être un caractère comme 30 lignes)
Git, c'est un autre monde et, une usine à gaz
templates (MVC / Modèle Vue Contrôleur)
Dans ton code tu mélanges "tout" dans une seule fonction (exemple outils.py# publication()), normalement c'est:
- fonction pour requete au serveur (get Datas)
- fonction traite le résultat
- fonction: on injecte le résultat dans un template (la Vue)
les moteurs de templates ont un langage pour traiter nos données "brutes" avec des bouches FOR et des IF
avoir des fonctions setup.py#choisirCritere() ou setup.py#formulaireRechercheEditionSuppression(), listeMiniatures() ... c'est typiquement ce que fait un moteur de template
Ton code ... ce mélange, c'est typiquement ce que l'on faisait il y a 20 ans avec php (mais php était à l'origine un moteur de template!)
---------
Si ce code est "uniquement pour toi", il n'y a aucunement mort d'homme, juste des choses peuvent être améliorées (dans le temps) prochainement, il faut que tu regardes du coté de MVC ;)
C'est sûr que j'ai des tas de choses à apprendre. Pour l'instant, je souhaite surtout débuguer et optimiser ce que j'ai fait dans l'architecture actuelle. Ça marche pas mal, en fait. Le tout est assez simple, et à ses débuts tout au moins, concernera peu de monde, car mes thèmes ne sont pas commerciaux. C'est pourquoi je pense pouvoir gérer les imperfections architecturales.
Cependant, comme j'ai en tête des tas d'extensions, surtout dans le domaine de l'enseignement des maths, l'implémentation de jeux à plusieurs, etc., il est possible dans l'avenir que la complexité grandissante me contraigne à repenser cette architecture. Mais je n'en suis pas là pour l'instant.
Le mot "reproche" était pas bien choisi. "critique" convient mieux !