Python dispose-t-il d'un moyen simple et intégré d'encoder / décoder des chaînes à l'aide d'un mot de passe?
Quelque chose comme ça:
>>> encode('John Doe', password = 'mypass')
'sjkl28cn2sx0'
>>> decode('sjkl28cn2sx0', password = 'mypass')
'John Doe'
Ainsi, la chaîne «John Doe» est chiffrée sous la forme «sjkl28cn2sx0». Pour obtenir la chaîne d'origine, je "déverrouillerais" cette chaîne avec la clé 'mypass', qui est un mot de passe dans mon code source. J'aimerais que ce soit la façon dont je peux crypter / décrypter un document Word avec un mot de passe.
Je souhaite utiliser ces chaînes cryptées comme paramètres d'URL. Mon objectif est l'obscurcissement, pas une sécurité solide; rien de critique à la mission n'est encodé. Je me rends compte que je pourrais utiliser une table de base de données pour stocker des clés et des valeurs, mais j'essaie d'être minimaliste.
Réponses:
En supposant que vous ne recherchiez qu'une simple obfuscation qui obscurcira les choses pour l' observateur très occasionnel, et que vous ne cherchiez pas à utiliser des bibliothèques tierces. Je recommanderais quelque chose comme le chiffre Vigenere. C'est l'un des plus puissants des chiffrements anciens simples.
Chiffre de Vigenère
C'est rapide et facile à mettre en œuvre. Quelque chose comme:
Le décodage est à peu près le même, sauf que vous soustrayez la clé.
Il est beaucoup plus difficile de casser si les chaînes que vous encodez sont courtes et / ou s'il est difficile de deviner la longueur de la phrase de passe utilisée.
Si vous recherchez quelque chose de cryptographique, PyCrypto est probablement votre meilleur pari, bien que les réponses précédentes négligent certains détails: le mode ECB dans PyCrypto nécessite que votre message soit un multiple de 16 caractères. Donc, vous devez pad. De plus, si vous souhaitez les utiliser comme paramètres d'URL, utilisez
base64.urlsafe_b64_encode()
plutôt que le standard. Cela remplace quelques-uns des caractères de l'alphabet base64 par des caractères sécurisés pour les URL (comme son nom l'indique).Cependant, vous devez être absolument certain que cette très fine couche d'obfuscation suffit à vos besoins avant de l'utiliser. L'article de Wikipédia auquel j'ai lié fournit des instructions détaillées pour casser le chiffre, de sorte que toute personne avec une détermination modérée pourrait facilement le casser.
la source
'str' object cannot be interpreted as an integer
Comme vous déclarez explicitement que vous voulez l'obscurité et non la sécurité, nous éviterons de vous réprimander pour la faiblesse de ce que vous suggérez :)
Donc, en utilisant PyCrypto:
Si quelqu'un met la main sur votre base de données et votre base de code, il pourra décoder les données cryptées. Gardez votre
secret_key
sécurité!la source
encrypt
fonction particulière est avec état dlitz.net/software/pycrypto/api/current/… donc vous ne devriez pas essayer de la réutiliser.Python n'a pas de schémas de chiffrement intégrés, non. Vous devez également prendre au sérieux le stockage de données cryptées; des schémas de cryptage triviaux qu'un développeur considère comme non sécurisés et un schéma de jouet peut très bien être confondu avec un schéma sécurisé par un développeur moins expérimenté. Si vous cryptez, cryptez correctement.
Cependant, vous n'avez pas besoin de beaucoup de travail pour implémenter un schéma de cryptage approprié. Tout d'abord, ne réinventez pas la roue de cryptographie , utilisez une bibliothèque de cryptographie de confiance pour gérer cela pour vous. Pour Python 3, cette bibliothèque de confiance est
cryptography
.Je recommande également que le cryptage et le décryptage s'appliquent aux octets ; encoder d'abord les messages texte en octets;
stringvalue.encode()
encode en UTF8, facilement rétabli en utilisantbytesvalue.decode()
.Enfin, lors du cryptage et du décryptage, nous parlons de clés , pas de mots de passe. Une clé ne doit pas être mémorable par un humain, c'est quelque chose que vous stockez dans un endroit secret mais lisible par machine, alors qu'un mot de passe peut souvent être lisible et mémorisé par l'homme. Vous pouvez dériver une clé d'un mot de passe, avec un peu de soin.
Mais pour une application Web ou un processus s'exécutant dans un cluster sans qu'une attention humaine ne soit nécessaire pour continuer à l'exécuter, vous souhaitez utiliser une clé. Les mots de passe sont utilisés lorsque seul un utilisateur final a besoin d'accéder aux informations spécifiques. Même dans ce cas, vous sécurisez généralement l'application avec un mot de passe, puis échangez des informations cryptées à l'aide d'une clé, peut-être attachée au compte utilisateur.
Chiffrement à clé symétrique
Fernet - AES CBC + HMAC, fortement recommandé
La
cryptography
bibliothèque comprend la recette Fernet , une recette des meilleures pratiques pour l'utilisation de la cryptographie. Fernet est un standard ouvert , avec des implémentations prêtes dans un large éventail de langages de programmation et il intègre le cryptage AES CBC pour vous avec des informations de version, un horodatage et une signature HMAC pour empêcher la falsification des messages.Fernet facilite le chiffrement et le déchiffrement des messages et vous protège. C'est la méthode idéale pour crypter des données avec un secret.
Je vous recommande d'utiliser
Fernet.generate_key()
pour générer une clé sécurisée. Vous pouvez également utiliser un mot de passe (section suivante), mais une clé secrète complète de 32 octets (16 octets pour chiffrer avec, plus 16 autres pour la signature) sera plus sécurisée que la plupart des mots de passe auxquels vous pourriez penser.La clé que Fernet génère est un
bytes
objet avec des caractères base64 URL et fichier sûr, donc imprimable:Pour crypter ou décrypter des messages, créez une
Fernet()
instance avec la clé donnée et appelezFernet.encrypt()
ouFernet.decrypt()
, le message en clair à crypter et le jeton crypté sont desbytes
objets.encrypt()
et lesdecrypt()
fonctions ressembleraient à:Démo:
Fernet avec mot de passe - clé dérivée du mot de passe, affaiblit quelque peu la sécurité
Vous pouvez utiliser un mot de passe au lieu d'une clé secrète, à condition d' utiliser une méthode de dérivation de clé forte . Vous devez ensuite inclure le salt et le nombre d'itérations HMAC dans le message, de sorte que la valeur chiffrée n'est plus compatible avec Fernet sans d'abord séparer salt, count et Fernet token:
Démo:
L'inclusion du sel dans la sortie permet d'utiliser une valeur de sel aléatoire, ce qui garantit à son tour que la sortie chiffrée est entièrement aléatoire, quelle que soit la réutilisation du mot de passe ou la répétition du message. L'inclusion du nombre d'itérations garantit que vous pouvez ajuster les performances du processeur au fil du temps sans perdre la capacité de déchiffrer les anciens messages.
Un mot de passe seul peut être aussi sûr qu'une clé aléatoire Fernet de 32 octets, à condition de générer un mot de passe correctement aléatoire à partir d'un pool de taille similaire. 32 octets vous donne un nombre de 256 ^ 32 touches, donc si vous utilisez un alphabet de 74 caractères (26 majuscules, 26 minuscules, 10 chiffres et 12 symboles possibles), votre mot de passe doit comporter au moins
math.ceil(math.log(256 ** 32, 74))
== 42 caractères. Cependant, un plus grand nombre d'itérations HMAC bien sélectionnées peut atténuer quelque peu le manque d'entropie, car cela rend beaucoup plus coûteux pour un attaquant de se frayer un chemin.Sachez simplement que le choix d'un mot de passe plus court mais toujours raisonnablement sécurisé ne paralysera pas ce schéma, il réduit simplement le nombre de valeurs possibles qu'un attaquant par force brute devrait rechercher; assurez-vous de choisir un mot de passe suffisamment fort pour vos exigences de sécurité .
Alternatives
Obscurcissant
Une alternative est de ne pas crypter . Ne soyez pas tenté d'utiliser simplement un chiffrement à faible sécurité ou une implémentation à domicile de, disons Vignere. Il n'y a pas de sécurité dans ces approches, mais peuvent donner à un développeur inexpérimenté qui a la tâche de maintenir votre code à l'avenir l'illusion de la sécurité, ce qui est pire que pas de sécurité du tout.
Si tout ce dont vous avez besoin est d'obscurité, base64 les données; pour les exigences de sécurité URL, la
base64.urlsafe_b64encode()
fonction est correcte. N'utilisez pas de mot de passe ici, encodez simplement et vous avez terminé. Tout au plus, ajoutez un peu de compression (commezlib
):Cela se transforme
b'Hello world!'
enb'eNrzSM3JyVcozy_KSVEEAB0JBF4='
.Intégrité uniquement
Si tout ce dont vous avez besoin est un moyen de vous assurer que les données peuvent être fiables pour ne pas être modifiées après avoir été envoyées à un client non approuvé et reçues en retour, alors vous voulez signer les données, vous pouvez utiliser la
hmac
bibliothèque pour cela avec SHA1 (toujours considéré comme sécurisé pour la signature HMAC ) ou mieux:Utilisez-le pour signer les données, puis attachez la signature avec les données et envoyez-la au client. Lorsque vous recevez les données, divisez les données et la signature et vérifiez. J'ai défini l'algorithme par défaut sur SHA256, vous aurez donc besoin d'une clé de 32 octets:
Vous voudrez peut-être regarder la
itsdangerous
bibliothèque , qui contient tout cela avec la sérialisation et la désérialisation dans divers formats.Utilisation du cryptage AES-GCM pour assurer le cryptage et l'intégrité
Fernet s'appuie sur AEC-CBC avec une signature HMAC pour assurer l'intégrité des données cryptées; un attaquant malveillant ne peut pas nourrir votre système de données absurdes pour garder votre service occupé à tourner en rond avec une mauvaise entrée, car le texte chiffré est signé.
Le chiffrement par blocs en mode Galois / Counter produit un texte chiffré et une étiquette pour servir le même but, donc peut être utilisé pour servir les mêmes buts. L'inconvénient est que, contrairement à Fernet, il n'y a pas de recette universelle facile à utiliser à réutiliser sur d'autres plates-formes. AES-GCM n'utilise pas non plus de remplissage, donc ce texte chiffré de chiffrement correspond à la longueur du message d'entrée (alors que Fernet / AES-CBC crypte les messages en blocs de longueur fixe, obscurcissant quelque peu la longueur du message).
AES256-GCM prend le secret habituel de 32 octets comme clé:
puis utilisez
J'ai inclus un horodatage pour prendre en charge les mêmes cas d'utilisation de durée de vie que Fernet prend en charge.
Autres approches sur cette page, en Python 3
AES CFB - comme CBC mais sans besoin de pad
C'est l'approche que suit All Іѕ Vаиітy , quoique incorrectement. Ceci est la
cryptography
version, mais notez que j'inclus l'IV dans le texte chiffré , il ne doit pas être stocké en tant que global (la réutilisation d'un IV affaiblit la sécurité de la clé, et le stocker en tant que module global signifie qu'il sera re-généré la prochaine invocation Python, rendant tout le texte chiffré indéchiffrable):Il n'y a pas de blindage supplémentaire d'une signature HMAC et il n'y a pas d'horodatage; vous devrez les ajouter vous-même.
Ce qui précède illustre également à quel point il est facile de combiner incorrectement les blocs de base de la cryptographie; Toute manipulation incorrecte de la valeur IV par Vаиітy peut entraîner une violation de données ou tous les messages cryptés sont illisibles parce que l'IV est perdu. L'utilisation de Fernet vous protège à la place de telles erreurs.
AES ECB - non sécurisé
Si vous avez précédemment implémenté le chiffrement AES ECB et que vous devez toujours le prendre en charge dans Python 3, vous pouvez toujours le faire avec
cryptography
. Les mêmes mises en garde s'appliquent, ECB n'est pas suffisamment sécurisé pour les applications réelles . Ré-implémenter cette réponse pour Python 3, en ajoutant la gestion automatique du remplissage:Encore une fois, il manque la signature HMAC et vous ne devriez pas utiliser ECB de toute façon. Ce qui précède n'est là que pour illustrer ce qui
cryptography
peut gérer les blocs de construction cryptographiques courants, même ceux que vous ne devriez pas utiliser.la source
Le "encoded_c" mentionné dans la réponse de chiffrement Vigenere de @ smehmood devrait être "key_c".
Voici les fonctions d'encodage / décodage fonctionnelles.
Avertissement: comme le suggèrent les commentaires, cela ne doit pas être utilisé pour protéger les données dans une application réelle, sauf si vous lisez ceci et que cela ne vous dérange pas de parler avec des avocats:
Quel est le problème avec le cryptage XOR?
la source
encodedmsg = encode('mypassword', 'this is the message éçàèç"')
print encodedmsg
print decode('mypassword', encodedmsg)
cela fonctionne très bien.Voici une version Python 3 des fonctions de l » @qneill réponse :
Le codage / décodage supplémentaire est nécessaire car Python 3 a divisé les chaînes / tableaux d'octets en deux concepts différents et a mis à jour leurs API pour refléter cela.
la source
.encode()).decode()
. dans le retour deencode()
, et.decode()
dans la deuxième ligne dansdecode()
.Avertissement: comme mentionné dans les commentaires, cela ne doit pas être utilisé pour protéger des données dans une application réelle.
Quel est le problème avec le cryptage XOR?
/crypto/56281/breaking-a-xor-cipher-of-known-key-length
https://github.com/hellman/xortool
Comme cela a été mentionné, la bibliothèque PyCrypto contient une suite de chiffrements. Le "chiffrement" XOR peut être utilisé pour faire le sale boulot si vous ne voulez pas le faire vous-même:
Le chiffrement fonctionne comme suit sans avoir à remplir le texte en clair:
Crédit à https://stackoverflow.com/a/2490376/241294 pour les fonctions d'encodage / décodage base64 (je suis un novice en python).
la source
sudo pip3 install pycrypto
.Voici une implémentation du cryptage et du décryptage URL Safe utilisant AES (PyCrypto) et base64.
Si vous rencontrez un problème comme celui-ci, utilisez https://bugs.python.org/issue4329 (
TypeError: character mapping must return integer, None or unicode
)str(cipher)
lors du décodage comme suit:Tester:
la source
TypeError: Object type <class 'str'> cannot be passed to C code
.b'...'
, j'ai édité la réponse pour référence future!Fonctionnement des fonctions d'encodage / décodage en python3 (très peu adapté de la réponse de qneill):
la source
Merci pour ces bonnes réponses. Rien d'original à ajouter, mais voici quelques réécritures progressives de la réponse de qneill en utilisant des fonctionnalités Python utiles. J'espère que vous conviendrez qu'ils simplifient et clarifient le code.
la source
Si vous voulez être en sécurité, vous pouvez utiliser Fernet, qui est cryptographiquement sain. Vous pouvez utiliser un «sel» statique si vous ne voulez pas le stocker séparément - vous ne perdrez que la prévention des attaques par dictionnaire et arc-en-ciel. Je l'ai choisi parce que je peux choisir des mots de passe longs ou courts », ce qui n'est pas si facile avec AES.
Si c'est trop compliqué, quelqu'un a suggéré simplecrypt
la source
Je vais donner 4 solutions:
1) Utilisation du cryptage Fernet avec la
cryptography
bibliothèqueVoici une solution utilisant le package
cryptography
, que vous pouvez installer comme d'habitude avecpip install cryptography
:Vous pouvez adapter avec votre propre sel, nombre d' itérations, etc. Ce code est pas très loin de la réponse de @ HCLivess mais le but ici est d'avoir prêt à l'emploi
encrypt
et lesdecrypt
fonctions. Source: https://cryptography.io/en/latest/fernet/#using-passwords-with-fernet .Remarque: utilisez
.encode()
et.decode()
partout si vous voulez des chaînes'John Doe'
au lieu d'octets commeb'John Doe'
.2) Chiffrement AES simple avec
Crypto
bibliothèqueCela fonctionne avec Python 3:
Remarque: vous pouvez supprimer
base64.b64encode
et.b64decode
si vous ne voulez pas de sortie lisible en texte et / ou si vous voulez quand même enregistrer le texte chiffré sur le disque sous forme de fichier binaire.3) AES utilisant une meilleure fonction de dérivation de clé de mot de passe et la possibilité de tester si "mauvais mot de passe entré", avec
Crypto
bibliothèqueLa solution 2) avec AES "mode CFB" est correcte, mais présente deux inconvénients: le fait que cela
SHA256(password)
puisse être facilement forcé avec une table de recherche, et qu'il n'y a aucun moyen de tester si un mot de passe incorrect a été saisi. Ceci est résolu ici par l'utilisation d'AES en "mode GCM", comme discuté dans AES: comment détecter qu'un mot de passe incorrect a été saisi? et Cette méthode pour dire «Le mot de passe que vous avez entré est incorrect» est-elle sécurisée? :4) Utilisation de RC4 (aucune bibliothèque nécessaire)
Adapté de https://github.com/bozhu/RC4-Python/blob/master/rc4.py .
(Obsolète depuis les dernières modifications, mais conservé pour référence future): j'ai eu des problèmes avec Windows + Python 3.6 + toutes les réponses impliquant
pycrypto
(impossiblepip install pycrypto
sur Windows) oupycryptodome
(les réponses ici ontfrom Crypto.Cipher import XOR
échoué car ellesXOR
ne sont pas prises en charge par cettepycrypto
fourchette; et les solutions utilisant ont... AES
échoué aussi avecTypeError: Object type <class 'str'> cannot be passed to C code
). De plus, la bibliothèquesimple-crypt
a unepycrypto
dépendance, ce n'est donc pas une option.la source
password_encrypt()
.Quiconque est venu ici (et le bountier) semblait chercher des one-liners avec peu de configuration, ce que les autres réponses ne fournissent pas. Je propose donc base64.
Maintenant, gardez à l'esprit qu'il s'agit d'un obscurcissement de base uniquement, et qu'il est pas possible pour la sécurité ** , mais voici quelques one-liners:
Quelques points à noter:
bytes()
etbytes::decode()
=
caractères. Les gens comme moi vont absolument les décoder dans la console javascript lorsque nous les voyons sur des sites Web. C'est aussi simple quebtoa(string)
(js)Maintenant, si ce que vous vouliez n'avait même pas besoin d'une clé d'aucune sorte, mais juste d'un obscurcissement, vous pouvez encore une fois simplement utiliser base64, sans aucun type de clé:
la source
Fernet(key).encrypt(message)
c'est juste une expression comme votre appel base64.key
complètement le fichier. Les charges de développeurs vont sans prêter attention et copier - coller de débordement de la pile et ne prennent la clé secrète. Si vous devez l'inclure, alors à tout le moins ne pas l'utiliser et avertir ou lever une exception si elle est quand même utilisée. Ne sous-estimez pas la folie de la culture du copier-coller et vos responsabilités à remplir des fonctions saines.Cela fonctionne mais la longueur du mot de passe doit être exactement
8
. Ceci est simple et nécessite pyDes .PRODUCTION:
la source
Une autre implémentation du code @qneill qui inclut la somme de contrôle CRC du message d'origine, elle lève une exception si la vérification échoue:
la source
Vous pouvez utiliser AES pour crypter votre chaîne avec un mot de passe. Cependant, vous voudrez choisir un mot de passe assez fort pour que les gens ne puissent pas facilement deviner ce que c'est (désolé je ne peux pas m'en empêcher. Je suis un weenie de sécurité en herbe).
AES est puissant avec une bonne taille de clé, mais il est également facile à utiliser avec PyCrypto.
la source
Les bibliothèques externes fournissent des algorithmes de chiffrement à clé secrète.
Par exemple, le
Cypher
module de PyCrypto propose une sélection de nombreux algorithmes de chiffrement:Crypto.Cipher.AES
Crypto.Cipher.ARC2
Crypto.Cipher.ARC4
Crypto.Cipher.Blowfish
Crypto.Cipher.CAST
Crypto.Cipher.DES
Crypto.Cipher.DES3
Crypto.Cipher.IDEA
Crypto.Cipher.RC5
Crypto.Cipher.XOR
MeTooCrypto est un
Python
wrapper pour OpenSSL et fournit (entre autres fonctions) une bibliothèque de cryptographie polyvalente complète. Des chiffrements symétriques (comme AES) sont inclus.la source
si vous souhaitez un cryptage sécurisé:
pour python 2, vous devez utiliser keyczar http://www.keyczar.org/
pour python 3, jusqu'à ce que keyczar soit disponible, j'ai écrit simple-crypt http://pypi.python.org/pypi/simple-crypt
ces deux éléments utiliseront le renforcement des clés, ce qui les rend plus sûrs que la plupart des autres réponses ici. et comme ils sont si faciles à utiliser, vous voudrez peut-être les utiliser même lorsque la sécurité n'est pas critique ...
la source
Donc, comme rien de critique à la mission n'est encodé , vous voulez simplement chiffrer pour l' obsfuscation .
Permettez-moi de vous présenter le chiffre de Céser
Le chiffrement de César ou changement de César, est l'une des techniques de chiffrement les plus simples et les plus connues. C'est un type de chiffrement de substitution dans lequel chaque lettre du texte brut est remplacée par une lettre à un nombre fixe de positions dans l'alphabet. Par exemple, avec un décalage à gauche de 3, D serait remplacé par A, E deviendrait B, et ainsi de suite.
Exemple de code pour votre référence:
Avantages: il répond à vos exigences et est simple et fait l'encodage "y".
Inconvénient: peut être craqué par de simples algorithmes de force brute (très peu probable que quiconque essaie de parcourir tous les résultats supplémentaires).
la source
Ajout d'un autre code avec décoder et encoder pour référence
la source