Python實作課程

第七堂課 : Password Manager

2022 / 6 / 17

Tony


古典密碼

維吉尼亞密碼

a.k.a進階版凱薩密碼


加密原理 :
明文、密鑰:由字母組成的字串
把 A 到 Z 編號成 0 到 25
明文中第一個字母的位移量就是密鑰第一個字母的編號
第二個字母的位移量就是密鑰第二個字母的編號、……
如果密鑰長度比明文字母數短
就再從第一個字母開始用


明文:HSNU CRC
密鑰:CRSC

明文 H S N U C R C
密鑰 C R S C C R S
密文 J J F W E I U


因為每一個字母的位移量都不盡相同
所以不知道密鑰的情況下
要還原出明文是很困難的事
幾乎不可能


維吉尼亞表格


實作維吉尼亞密碼


要怎麼把字母位移?


我們利用ASCII(美國資訊交換標準代碼)


找到字元 c 對應的數字:ord(c)
找到數字 i 對應的字元:chr(i)


純字母版

def encryption(key, password): cipher = "" now = 0 for char in password: t = ord(char) - ord('A') k = ord( key[now] ) - ord('A') print(t+k) cipher += chr( ord('A') + (t+k)%26 ) now = (now + 1) % len(key) return cipher def decryption(key, password): cipher = "" now = 0 for char in password: t = ord(char) - ord('A') k = ord( key[now] ) - ord('A') print(t-k) cipher += chr( ord('A') + (t-k)%26) now = (now + 1) % len(key) return cipher

廣泛版(不局限於字母)

def encryption(key, password): cipher = "" now = 0 for char in password: k = ord( key[now] ) - ord('A') cipher += chr( (ord(char) + k)%126 ) now = (now + 1) % len(key) return cipher def decryption(key, password): cipher = "" now = 0 for char in password: k = ord( key[now] ) - ord('A') cipher += chr( (ord(char) - k)%126 ) now = (now + 1) % len(key) return cipher

我們將用它來加密/解密我們的密碼


Password Manager


有時候在很多網站創建很多帳號
其中每種帳號的密碼限制都不一樣
時間久了很容易忘記

這種時候就很需要Password Manager的幫忙


Process:

  1. 輸入Master password (用戶名,也是到時候加解密的key)
  2. 選擇瀏覽密碼還是新增密碼
  3. 如果新增密碼,輸入帳號名稱跟密碼,把密碼依照維吉尼亞密碼規定加密後連同帳號名稱存入記事本
  4. 如果瀏覽密碼,把目前所有的密碼解密之後連同帳號名稱秀出來
  5. 都沒事了就按q退出

如果master password輸入錯誤,就會無法看到既有的密碼


開始寫Code


  1. 輸入master password
key = input("What is the master password?")

  1. 選擇瀏覽密碼還是加新密碼
while True: mode= input("Would you like to add a new password or view existing ones (view, add), press q to quit? ").lower() if mode == 'q': break if mode == "view": view(key) elif mode == "add": add(key) else: print("Valid mode.") continue

加解密函式

def encryption(key, password): cipher = "" now = 0 for char in password: k = ord( key[now] ) - ord('A') cipher += chr( (ord(char) + k)%126 ) now = (now + 1) % len(key) return cipher def decryption(key, password): cipher = "" now = 0 for char in password: k = ord( key[now] ) - ord('A') cipher += chr( (ord(char) - k)%126 ) now = (now + 1) % len(key) return cipher

add()函式

password.txt 中新加一條密碼,包含用戶名稱跟密碼

  • with open("password.txt", 'a') as file:
    打開一個文件檔並做事情,把他想成一個if
    執行結束之後password.txt就會自動被關掉,很方便

輸入完會請使用者再確認一次


def add(key): print('') Done = False while not Done: name = input("Account name : ") password = input("Password : ") print('') print("Please double check the account name and password you\'ve typed in :") print("Account name :", name) print("Password :", password) correct = input("Type \"yes\" if they're correct, \"no\" if they're not : ").lower() print('') if correct == "yes": encrypted_password = encryption(key, password) # like a function. Once it's done, the file will be closed automatically. # a stands for "pen". Add sth to an existing file or create a new file if the file doesn't exist. # w stands for "write". Create a file or overwrite the file # r stands for "read". Just read. with open("password.txt", 'a') as file: file.write(name + '|' + encrypted_password + '\n') # 寫入密碼 Done = True elif correct == "no": print("Alright. Please type again.") continue else: print("Valid reaction.") continue

view()函式

把目前所有密碼都依照輸入的key解密後秀出來

  • file.readlines(len) : 取得文字檔file的所有文字,len默認是-1,代表所有行數
  • line.split('|') : 把line依照'|'切割成n個不同字元,大多數密碼不會包含'|',所以假設只利用原先用來分割的'|'切割出兩個字串
  • line.rstrip() : 去除line最後面的指定部分,默認是空白、換行等等

def view(key): print('') with open("password.txt", 'r') as file: for line in file.readlines(): data = line.rstrip() # delete the '\n' behind ecery line user, password = data.split('|') # "FB|123456789" -> ["FB", "123456789"] password = decryption(key, password) print("Account name :", user, "| Password :", password) print('')

恭喜各位完成Password Manager,
可以自己多加一些有趣的功能

Select a repo