Je viens de créer mon premier projet Python. Je suis sûr qu'il y a beaucoup d'améliorations qui pourraient être apportées, mais j'ai une question spécifique sur la façon de modifier mon code.

J'ai lu qu'il n'était pas judicieux d'utiliser des variables globales (en raison de problèmes de sécurité). Mais je ne sais pas comment faire fonctionner plusieurs fonctions ensemble (c'est-à-dire utiliser les mêmes variables) à moins qu'elles ne soient globales.

Le programme ci-dessous fait trois choses:

  1. Générez un mot de passe.
  2. Cryptez ce mot de passe.
  3. Décryptez le mot de passe.

Cependant, je n'ai déclaré des variables globales que dans la partie 2 pour crypter le mot de passe.

Ma question est: comment modifier le code pour éviter d'utiliser des globaux? J'ai collé tout le code ci-dessous pour référence, mais les globaux sont déclarés dans def listToString() et def passEncryptor():.

import random

#variables to hold a list and a string
Password = []
Encrypted = ''

#variables to hold the specific characters
#to use in creating the password
a = 'abcdefghijklmnopqrstuvwxyz'
b = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
c = '0123456789'
d = '!@#$%^&*()'

#variable holds all possible values
#that could be found in the password
e = a + b + c + d

#variables will randomize the password length
sm = random.randint(2,3)
lg = random.randint(3,4)

#function generates a randomized password
def passwordGenerator() :

    #append elements from variables a - d
    #to the Password variable
    for x in range(sm) :
        Password.append(random.choice(a))
    for x in range(sm) :
        Password.append(random.choice(b))
    for x in range(lg) :
        Password.append(random.choice(c))
    for x in range(sm) :
        Password.append(random.choice(d))

    #randomize the order of the elements    
    random.shuffle(Password)

    #ensure the first element is a letter
    Password.insert(0, random.choice(a))

    #print to show that the program worked
    print(Password)

#call function to generate a randomized password
passwordGenerator()

#function to store 5 random elements in a string
def listToString() :

    #can't seem to get this to work
    #without using a global variable
    global rand5
    rand5 = ''
    x = random.choices(e, k=5)
    for val in x :
        rand5 += val
    return rand5

#for each element in the password
#add the random 5 elements from listToString()
def passEncryptor():

    global tempPass
    tempPass = ''
    for val in Password :

        #gets 5 new random elements
        listToString()

        #concatenate the random elements
        #with the real password
        tempPass += val + rand5

    print(tempPass)
passEncryptor()

#function to unencrypt an encrypted password
def passDecryptor():

    #convert the encrypted string to a list
    encryptedList = []
    for val in tempPass :
        encryptedList.append(val)

    #remove the random 5 elements    
    decrypt = encryptedList[::6]
    decrypted = ''
    #convert back to a string
    for val in decrypt :
        decrypted += val

    print(decrypted)

passDecryptor()
1
Kyle Marvin 19 avril 2020 à 22:43

2 réponses

Meilleure réponse

Dans ce cas, cela revient vraiment à un manque de connaissances - vous ne tirez pas parti des paramètres de fonction - je suppose que vous ne savez pas ce que c'est, car si vous le faisiez, vous les préféreriez aux variables globales.

Je ne sais pas si la «sécurité» est exactement ce que vous sacrifiez lorsque vous utilisez des variables globales. Bien sûr, je peux penser à des exemples hypothétiques, et je suis sûr que quelqu'un peut citer des exemples réels où l'utilisation de variables globales était un problème de sécurité majeur ... Ce que je veux dire, c'est que l'utilisation de variables globales ne fait pas de votre programme intrinsèquement peu sûrs - c'est juste qu'il est très facile de les utiliser de manière incorrecte (y a-t-il un moyen correct?). Il existe de meilleures solutions disponibles pour résoudre les problèmes que vous pensez ne pouvoir résoudre qu'avec des variables globales.

Le code que vous avez publié illustre parfaitement le nœud des variables globales - Si moi, un utilisateur de votre programme, je veux générer plusieurs mots de passe, le résultat que j'obtiens est inattendu:

['d', 'q', '3', 'O', 'g', '1', '$', 'J', '&', '7']
dsLT(mq4N^Yy3(L)%iOr&VM3gTfaZq1&ud9B$RJJ1aJe6Nju&O2*rE7Zz@Y!
dq3Og1$J&7
>>> passwordGenerator()
['n', '&', 'E', ')', '7', '0', '&', 'O', '2', '1', '$', '3', 'q', 'q', 'k', 'J', 'B', '1', 'd', 'g']
>>> passwordGenerator()
['j', '9', 'd', '1', 'k', 'O', 'B', 'q', 'Q', '2', 'g', 'o', 'e', '7', '1', 'n', 'q', '$', 'J', '&', '!', '0', 'A', '!', 'E', ')', '3', '7', '&', '2']
>>> passwordGenerator()
['u', 'o', '!', ')', '0', 'j', 'h', '1', '!', 'q', '7', 'g', '$', '9', 'n', 'k', 'q', '1', '&', 'd', 'J', '2', 'B', '8', '3', '2', '&', '7', 'L', '*', 'O', '5', 'Q', 'e', '&', 'S', '2', 'E', 'A', 'x']
>>> passwordGenerator()
['o', 'h', 'u', '1', 'S', 'q', '&', '7', '$', 'g', '7', '8', '2', '3', 'J', '&', 'k', 'A', '9', 'q', '2', '1', '6', 'B', '0', '*', '&', '!', 'e', 'x', 'j', 'B', 'L', 'a', 'o', '9', ')', '$', 'n', '9', 'U', 's', '!', 'Q', 'E', '2', 'd', '&', '5', 'O']

passwordGenerator modifie l'état de la variable globale Password en y ajoutant des éléments à chaque fois que la fonction est appelée. D'une manière générale, la fonction modifie l'état d'une variable (qui se trouve en dehors de la portée de la fonction) de manière inattendue. C'est pourquoi les variables globales peuvent être source de problèmes, qu'il s'agisse de sécurité ou non.

Cela n'a aucun rapport, mais vous faites également des choses inutiles, comme mélanger Password après y avoir ajouté des caractères aléatoires. Voici à quoi cela pourrait ressembler avec les paramètres de fonction:

def get_random_password(alphabet):
    from random import randint, choices

    password_length = randint(5, 16)
    password = choices(alphabet, k=password_length)

    return "".join(password)


def get_encrypted(alphabet, plaintext):
    from random import choices

    return "".join(char + "".join(choices(alphabet, k=5)) for char in plaintext)

def get_decrypted(encrypted_plaintext):
    return encrypted_plaintext[::6]

def main():
    import string

    alphabet = string.digits + string.ascii_letters + string.punctuation
    # alphabet = string.printable.rstrip()

    password = get_random_password(alphabet)
    encrypted = get_encrypted(alphabet, password)
    decrypted = get_decrypted(encrypted)

    print(f"The password is \"{password}\"")
    print(f"Encrypted: \"{encrypted}\"")
    print(f"Decrypted: \"{decrypted}\"")


if __name__ == "__main__":
    main()

Production:

The password is "O*L7~"
Encrypted: "OiL)V\*I={w&LX5"2-7WF/\+~5%_mP"
Decrypted: "O*L7~"
>>> 

J'ai également ajouté un point d'entrée main et j'ai un peu plus profité de la bibliothèque standard. C'est tangentiel, mais vous ne "cryptez" pas vraiment la chaîne à proprement parler - c'est plus comme une obscurcissement, mais peu importe.

1
Paul M. 19 avril 2020 à 20:33

Créez une classe et placez vos fonctions en tant que méthodes de classe et variables en tant que membres de ce classer.

0
Olivier Pirson 19 avril 2020 à 20:44