Perl6: 密碼產生器
作者:gugod 發佈於: #perl6每每說到「密碼產生器」,就不得不去複習一下 xkcd/936 這則漫畫。
xkcd 936 這則漫畫在闡明的重點其實就是密碼要「夠長」。密碼長則難以猜中而強度高。 從夠大的英文字典檔中隨機揀四個英文單字出來所組成的密碼,其強度已然超過了用許多 特殊符號組成的短密碼。
那麼就以此為題吧:如何從一個英文字典檔中隨機揀四個英文單字出來、組成密碼?
假設已有個陣列 @dict
,內含了一個英文字典中所有單字,那麼要
從其中隨機選一個元素出來的做法為:
@dict.pick()
是的,這件事在 Perl6 語言裡是個內建函式:pick。這個函式定義在許多種容器類 別上,表示「從容器中選個東西出來」的意思。
事實上這個函式還能收個參數,表示要揀出的元素個數。所以要四個的話,就是:
@dict.pick(4)
而且被 pick
選中的,還是不重複的元素。更精確地說,是在 @dict
中不同位置的
元素。如果 "apple"
在 @dict
中出現了兩次,兩個都被挑中的機率不會是零。
若要刻意容許選出重複元素的可能性,可以改成呼叫 pick()
四次的做法:
(1..4).map({ dicta.pick() })
那麼 @dict
的內容又要從何而來呢?其實有許多進行中的字典計畫,其授權為公開的,
可自行取用。像是:FreeDict、WordNet 等等。但,其實在 macOS 上已有個
承襲自 FreeBSD 的字典檔: /usr/share/dict/words
。此字典檔來源為
"Webster's Second International",短名 "web2a",是個於 1934 年出版的字典。在著作權過期後,被
廣泛地用於各種 UNIX 系統上。一般是當作拼字檢查的資料來源。在 FreeBSD / macOS
以外的系統上,這檔案的內容可能會不同,但格式都是相同的。
這個檔案格式很簡單。純文字,一列一個單字。就這樣。因此要將其讀成陣列很也容易。
my @dict = open("/usr/share/dict/words").lines();
是的,這個 lines
也是個內建於 IO::Handle
類別上的方法。上述寫法
會把整個檔案讀進來,依換行字符切開,再把切下來的各部份裝進陣列 @dict
當中。
各元素內容是不包含換行字符的。這是預設行為,但有參數可以微調。
而既然密碼只要四個字,其實也可以直接串下去,最後直接印出來:
open("/usr/share/dict/words").lines().pick(4).join().say;
若無參數,方法呼叫所用的那組空括號就可以省略不寫:
open("/usr/share/dict/words").lines.pick(4).join.say;
這程式既然如此短,也可以直接以一行文(oneliner)寫完收工:
# perl6 -e 'open("/usr/share/dict/words").lines.pick(4).join.say'
phalangiticatherosclerosisrupturedsnarly
然後可以包成 zsh 函式,省得每次都在打那一大串程式碼:
function pw() { perl6 -e 'open("/usr/share/dict/words").lines.pick(4).join.say' }
效果相同
# pw
irrelategushingnessuntumbledrigorism
另外廣告:Javascript / Web UI 版: pw