├── .circleci └── config.yml ├── .gitignore ├── LICENSE.txt ├── Makefile ├── README.md ├── adjacency ├── adjacmartix_test.go └── adjcmartix.go ├── data ├── bindata.go └── data │ ├── Dvorak.json │ ├── English.json │ ├── FemaleNames.json │ ├── Keypad.json │ ├── L33t.json │ ├── MacKeypad.json │ ├── MaleNames.json │ ├── Passwords.json │ ├── Qwerty.json │ └── Surnames.json ├── entropy ├── entropyCalculator.go └── entropyCalculator_test.go ├── frequency └── frequency.go ├── fuzz ├── fuzz.go └── workdir │ └── corpus │ ├── 0379f1e9bc4a1c7fc02bd4872c66c73980064beb-1 │ ├── 0449cf41cee451d4bc01593edffc33dbe4cc6ed8-5 │ ├── 057c9afef29f89efc31ce51a089e2ad07be862df │ ├── 0939a9a26bc38f1987a4466571e5eee9118c362f │ ├── 0a57cb53ba59c46fc4b692527a38a87c78d84028-6 │ ├── 0d651898c91e920fa9504f9237401a1df4a71230-5 │ ├── 11ed49d6fd3446798f01865b44a88a19d110c310-5 │ ├── 1634243a95c2478d2c760f5c30951dce97574987-3 │ ├── 174d2deb68324c0b8bbd980bd86d06d9745e9b3c-5 │ ├── 197f19525eea560f3e2a93773fd4659da57af9ea-2 │ ├── 1abd5024b4ab05b023659daa1b920b9db1e13674-5 │ ├── 21f7d5621eeeadc6d44de46fddcd21f3b0904289-5 │ ├── 221d7c4034d32c379d10225c3b8e569f9b5a90bc-5 │ ├── 2aae52a530b36be8974f6643bcb481f63ccbde1b-5 │ ├── 2b2c9df7e2a3027967cd9338759453b12cd7a3ff-1 │ ├── 2e8a46cec8efb82bea0f6dd69e4447610420df19-3 │ ├── 3312b1dbba75726aa90a90e37c9a2cb501467e08-5 │ ├── 3516d6010dac3e1d7581f415a3842226c7eb21ae-6 │ ├── 366860784d965ee1640bf5bfd00f2c54315f93e5-1 │ ├── 3702236b11bd1b301fd4dff3c3de331dfc151c29-3 │ ├── 399e57b2fc5fbdc129e4b61e7818dadec3393886-6 │ ├── 3c52042a2628722948972dc55b7faa436e4bcbb6-4 │ ├── 3d3d0067fcceec6b05977e38045960f452649d0e-1 │ ├── 3f7f6a85b994371d6d2504cadabcd60018e5c4aa-5 │ ├── 4709344ed6b1145c0172175c61403c4745035443-4 │ ├── 47e3bb7dde4aabca19f5efc459e4423ceb7ab74c-2 │ ├── 48f03a7b4c83fd21f52124bd5150ef0b2b3e8032-6 │ ├── 492a7b0ae52963cb75a2e7a044ba49e58285621e-3 │ ├── 4f84679c1427b0081732ee473bef237010075356-5 │ ├── 4fc780d545d57f9e2cedcff2259c2751c93a2002-5 │ ├── 51edc2abfdba3a50e391323c4ba45559750ef5ef-6 │ ├── 55e79155c1a348c03e4e4b71762819fe9efc6303-6 │ ├── 577869d54ae0beeaccd315f67777b801c53b9744-3 │ ├── 596022f185b0bb13196bec3de9ab0100384c12fb-2 │ ├── 5a0a6bfc5fa088bec5cbaedfa71dc5d6f7f77b46 │ ├── 5aefcaf6c8935ed7fc778b9b26905ac205ab8849-4 │ ├── 5be00875facc075657bde848eac3e9c63ec849bb-2 │ ├── 62c8835e75525875f75f82944c9df50e11afb9cc │ ├── 632cf624060aff03df13a547d60a8ad72b2b4b02-1 │ ├── 64f907d2737089067ca4bfe099ef0a63938dd5de │ ├── 6a33fdefa8afdbf1e6154912735b295717ce2eb6-1 │ ├── 6d1c216c69100abd5c53d49ac1e35bee65d4ab70-3 │ ├── 71c9db717578b9ee49a59e69375c16c0627dffef-3 │ ├── 7db1aa4b84213fad96badd59a197948bcc984195-4 │ ├── 8312e3532bbc3c5b6273ec4af64dd554e0f5b836-4 │ ├── 83abf7ddc4394233286c9210087dabf03b19a153-3 │ ├── 849cc30a6fb31a7978cd7e6f7d68cbcedd2dbfe7-5 │ ├── 8750ec9ddfe293cd1dc39b4245c21c270f8f52b7-4 │ ├── 889046a524770e5e165728f24e54765eb18cbd08-1 │ ├── 8a0d5a57533dd35f721690857a5e64a65a7e294e-5 │ ├── 8d96642d5dd2a537a5761c691f61af7551034bf0 │ ├── 8ff92c267f61da0818b23b4dd4df0c6fd571eb98-5 │ ├── 91c1bb4961e8972dcd057c7162e6ffbf337422c3-6 │ ├── 97140203053231c6afa57a7d3e42793e786b3c0d │ ├── 99180e7785954b7e75337c7d68a878b16359ddef-5 │ ├── 9a0e5b94555df3dd524cf954b7cd098d04c0c5d2 │ ├── 9f507d371a3beab3e95fb88db86c0ced13f96dca-1 │ ├── a3b2b4c9a873749376acd08f7e51381c4bd5d2ef-6 │ ├── a51e63c32726ae35f64151509fabbc82c8fd73fa-4 │ ├── a5a1deaea046a2a8fe3a5f54b6ac1e42c2d20443-4 │ ├── a60d1d9835e41888af15698172a415fbf9626445-3 │ ├── a8c081c4053e6fd1e4620df28803f32308279b1d-5 │ ├── ae4f281df5a5d0ff3cad6371f76d5c29b6d953ec-3 │ ├── afa8d4d4b28f4e13c30afc2c6d5982685614d4f9-4 │ ├── b28707e84c7f7e40c5f7ddc901c25054b66ee0d9-6 │ ├── b3af2d73132d1f991f8ef73eca1a8a98ad53f835-5 │ ├── b608555928c295732b6ffe9e08386dbcdc59651c │ ├── be108be24a7b904db41b5eae4a2957df53e84df8-5 │ ├── c1f2cf4bd49167996a6f1464802fa3c0becff9c1-3 │ ├── c9d123bd98167cb1093ba05f3873ae9c0e28e136-2 │ ├── cb8c7dec4b7dd839e050de86e4355f39e9ff446e-6 │ ├── d28321f0aa0a4a985af875add48dab7dfaf46a1b-2 │ ├── d97af67d4a25957f1995000fc5515d402c0aa473 │ ├── da39a3ee5e6b4b0d3255bfef95601890afd80709-2 │ ├── e1161af9333f4f87b04b5046261b26ec96df33a0-2 │ ├── e52e67036397fb8f6cc39ccfc635fcb7f01f7d38-5 │ ├── e8c0557385fa0e24f2abd06e83fb6b568aed8865-2 │ ├── e9e72a1bd62e3822b4345b1a027a930aca35d922-2 │ ├── ebcd8d722dde05d862048deebfe5bc4cb48a5f6f-5 │ ├── ef814cd79d18b9bf1df32f2a5279e31406970ac4-4 │ ├── f839a6d0ecaff3f478bcf3f51ce59da903d6a1d1 │ ├── f9b258b5b82e1253631e6eeb4e2459f645dc0e4c-4 │ ├── fbc2ae73c4537afe3f7ad1457ec3685e97ba32a8-1 │ └── fc1e27548a8e9191beb76c263c62f57fcc9b0855-3 ├── go.mod ├── go.sum ├── match └── match.go ├── matching ├── dateMatchers.go ├── dictionaryMatch.go ├── leet.go ├── leet_test.go ├── matching.go ├── matching_test.go ├── repeatMatch.go ├── sequenceMatch.go └── spatialMatch.go ├── scoring └── scoring.go ├── testapp └── main.go ├── utils └── math │ ├── mathutils.go │ └── mathutils_test.go ├── zxcvbn.go └── zxcvbn_test.go /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Golang CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-go/ for more details 4 | version: 2 5 | jobs: 6 | build: 7 | docker: 8 | # specify the version 9 | - image: circleci/golang:1.9 10 | 11 | # Specify service dependencies here if necessary 12 | # CircleCI maintains a library of pre-built images 13 | # documented at https://circleci.com/docs/2.0/circleci-images/ 14 | # - image: circleci/postgres:9.4 15 | 16 | #### TEMPLATE_NOTE: go expects specific checkout path representing url 17 | #### expecting it in the form of 18 | #### /go/src/github.com/circleci/go-tool 19 | #### /go/src/bitbucket.org/circleci/go-tool 20 | working_directory: /go/src/github.com/nbutton23/zxcvbn-go 21 | steps: 22 | - checkout 23 | - run: go get -u golang.org/x/lint/golint 24 | - run: make test 25 | - run: make lint -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | zxcvbn 2 | debug.test 3 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) Nathan Button 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PKG_LIST = $$( go list ./... | grep -v /vendor/ | grep -v "zxcvbn-go/data" ) 2 | 3 | .DEFAULT_GOAL := help 4 | 5 | .PHONY: help 6 | help: 7 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 8 | 9 | .PHONY: test 10 | test: ## Run `go test {Package list}` on the packages 11 | go test $(PKG_LIST) 12 | 13 | .PHONY: lint 14 | lint: ## Run `golint {Package list}` 15 | golint $(PKG_LIST) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a goLang port of python-zxcvbn and [zxcvbn](https://github.com/dropbox/zxcvbn), which are python and JavaScript password strength 2 | generators. zxcvbn attempts to give sound password advice through pattern 3 | matching and conservative entropy calculations. It finds 10k common passwords, 4 | common American names and surnames, common English words, and common patterns 5 | like dates, repeats (aaa), sequences (abcd), and QWERTY patterns. 6 | 7 | Please refer to https://dropbox.tech/security/zxcvbn-realistic-password-strength-estimation for the full details and 8 | motivation behind zxcbvn. The source code for the original JavaScript (well, 9 | actually CoffeeScript) implementation can be found at: 10 | 11 | https://github.com/lowe/zxcvbn 12 | 13 | Python at: 14 | 15 | https://github.com/dropbox/python-zxcvbn 16 | 17 | For full motivation, see: 18 | 19 | https://dropbox.tech/security/zxcvbn-realistic-password-strength-estimation 20 | 21 | ------------------------------------------------------------------------ 22 | Use 23 | ------------------------------------------------------------------------ 24 | 25 | The zxcvbn module has the public method PasswordStrength() function. Import zxcvbn, and 26 | call PasswordStrength(password string, userInputs []string). The function will return a 27 | result dictionary with the following keys: 28 | 29 | Entropy # bits 30 | 31 | CrackTime # estimation of actual crack time, in seconds. 32 | 33 | CrackTimeDisplay # same crack time, as a friendlier string: 34 | # "instant", "6 minutes", "centuries", etc. 35 | 36 | Score # [0,1,2,3,4] if crack time is less than 37 | # [10^2, 10^4, 10^6, 10^8, Infinity]. 38 | # (useful for implementing a strength bar.) 39 | 40 | MatchSequence # the list of patterns that zxcvbn based the 41 | # entropy calculation on. 42 | 43 | CalcTime # how long it took to calculate an answer, 44 | # in milliseconds. usually only a few ms. 45 | 46 | The userInputs argument is an splice of strings that zxcvbn 47 | will add to its internal dictionary. This can be whatever list of 48 | strings you like, but is meant for user inputs from other fields of the 49 | form, like name and email. That way a password that includes the user's 50 | personal info can be heavily penalized. This list is also good for 51 | site-specific vocabulary. 52 | 53 | Bug reports and pull requests welcome! 54 | 55 | ------------------------------------------------------------------------ 56 | Project Status 57 | ------------------------------------------------------------------------ 58 | 59 | Use zxcvbn_test.go to check how close to feature parity the project is. 60 | 61 | ------------------------------------------------------------------------ 62 | Acknowledgment 63 | ------------------------------------------------------------------------ 64 | 65 | Thanks to Dan Wheeler (https://github.com/lowe) for the CoffeeScript implementation 66 | (see above.) To repeat his outside acknowledgements (which remain useful, as always): 67 | 68 | Many thanks to Mark Burnett for releasing his 10k top passwords list: 69 | https://xato.net/passwords/more-top-worst-passwords 70 | and for his 2006 book, 71 | "Perfect Passwords: Selection, Protection, Authentication" 72 | 73 | Huge thanks to Wiktionary contributors for building a frequency list 74 | of English as used in television and movies: 75 | https://en.wiktionary.org/wiki/Wiktionary:Frequency_lists 76 | 77 | Last but not least, big thanks to xkcd :) 78 | https://xkcd.com/936/ 79 | -------------------------------------------------------------------------------- /adjacency/adjacmartix_test.go: -------------------------------------------------------------------------------- 1 | package adjacency 2 | 3 | import ( 4 | "github.com/stretchr/testify/assert" 5 | "testing" 6 | ) 7 | 8 | /* 9 | nbutton: Really the value is not as important to me than they don't change, which happened during development. 10 | */ 11 | func TestCalculateDegreeQwert(t *testing.T) { 12 | avgDegreeQwert := BuildQwerty().CalculateAvgDegree() 13 | 14 | assert.Equal(t, float64(1.5319148936170213), avgDegreeQwert, "Avg degree for qwerty should be 1.5319148936170213") 15 | } 16 | 17 | func TestCalculateDegreeDvorak(t *testing.T) { 18 | avgDegreeQwert := BuildDvorak().CalculateAvgDegree() 19 | 20 | assert.Equal(t, float64(1.5319148936170213), avgDegreeQwert, "Avg degree for dvorak should be 1.53191489361702135") 21 | } 22 | 23 | func TestCalculateDegreeKeypad(t *testing.T) { 24 | avgDegreeQwert := BuildKeypad().CalculateAvgDegree() 25 | 26 | assert.Equal(t, float64(0.6333333333333333), avgDegreeQwert, "Avg degree for keypad should be 0.6333333333333333") 27 | } 28 | 29 | func TestCalculateDegreeMacKepad(t *testing.T) { 30 | avgDegreeQwert := BuildMacKeypad().CalculateAvgDegree() 31 | 32 | assert.Equal(t, float64(0.65625), avgDegreeQwert, "Avg degree for mackeyPad should be 0.65625") 33 | } 34 | -------------------------------------------------------------------------------- /adjacency/adjcmartix.go: -------------------------------------------------------------------------------- 1 | package adjacency 2 | 3 | import ( 4 | "encoding/json" 5 | "log" 6 | 7 | "github.com/nbutton23/zxcvbn-go/data" 8 | ) 9 | 10 | // Graph holds information about different graphs 11 | type Graph struct { 12 | Graph map[string][]string 13 | averageDegree float64 14 | Name string 15 | } 16 | 17 | // GraphMap is a map of all graphs 18 | var GraphMap = make(map[string]Graph) 19 | 20 | func init() { 21 | GraphMap["qwerty"] = BuildQwerty() 22 | GraphMap["dvorak"] = BuildDvorak() 23 | GraphMap["keypad"] = BuildKeypad() 24 | GraphMap["macKeypad"] = BuildMacKeypad() 25 | GraphMap["l33t"] = BuildLeet() 26 | } 27 | 28 | //BuildQwerty builds the Qwerty Graph 29 | func BuildQwerty() Graph { 30 | data, err := data.Asset("data/Qwerty.json") 31 | if err != nil { 32 | panic("Can't find asset") 33 | } 34 | return getAdjancencyGraphFromFile(data, "qwerty") 35 | } 36 | 37 | //BuildDvorak builds the Dvorak Graph 38 | func BuildDvorak() Graph { 39 | data, err := data.Asset("data/Dvorak.json") 40 | if err != nil { 41 | panic("Can't find asset") 42 | } 43 | return getAdjancencyGraphFromFile(data, "dvorak") 44 | } 45 | 46 | //BuildKeypad builds the Keypad Graph 47 | func BuildKeypad() Graph { 48 | data, err := data.Asset("data/Keypad.json") 49 | if err != nil { 50 | panic("Can't find asset") 51 | } 52 | return getAdjancencyGraphFromFile(data, "keypad") 53 | } 54 | 55 | //BuildMacKeypad builds the Mac Keypad Graph 56 | func BuildMacKeypad() Graph { 57 | data, err := data.Asset("data/MacKeypad.json") 58 | if err != nil { 59 | panic("Can't find asset") 60 | } 61 | return getAdjancencyGraphFromFile(data, "mac_keypad") 62 | } 63 | 64 | //BuildLeet builds the L33T Graph 65 | func BuildLeet() Graph { 66 | data, err := data.Asset("data/L33t.json") 67 | if err != nil { 68 | panic("Can't find asset") 69 | } 70 | return getAdjancencyGraphFromFile(data, "keypad") 71 | } 72 | 73 | func getAdjancencyGraphFromFile(data []byte, name string) Graph { 74 | 75 | var graph Graph 76 | err := json.Unmarshal(data, &graph) 77 | if err != nil { 78 | log.Fatal(err) 79 | } 80 | graph.Name = name 81 | return graph 82 | } 83 | 84 | // CalculateAvgDegree calclates the average degree between nodes in the graph 85 | //on qwerty, 'g' has degree 6, being adjacent to 'ftyhbv'. '\' has degree 1. 86 | //this calculates the average over all keys. 87 | //TODO double check that i ported this correctly scoring.coffee ln 5 88 | func (adjGrp Graph) CalculateAvgDegree() float64 { 89 | if adjGrp.averageDegree != float64(0) { 90 | return adjGrp.averageDegree 91 | } 92 | var avg float64 93 | var count float64 94 | for _, value := range adjGrp.Graph { 95 | 96 | for _, char := range value { 97 | if len(char) != 0 || char != " " { 98 | avg += float64(len(char)) 99 | count++ 100 | } 101 | } 102 | 103 | } 104 | 105 | adjGrp.averageDegree = avg / count 106 | 107 | return adjGrp.averageDegree 108 | } 109 | -------------------------------------------------------------------------------- /data/data/Dvorak.json: -------------------------------------------------------------------------------- 1 | { 2 | "Graph": { 3 | "0": [ 4 | "9(", 5 | null, 6 | null, 7 | "[{", 8 | "lL", 9 | "rR" 10 | ], 11 | "1": [ 12 | "`~", 13 | null, 14 | null, 15 | "2@", 16 | "'\"", 17 | null 18 | ], 19 | "2": [ 20 | "1!", 21 | null, 22 | null, 23 | "3#", 24 | ",<", 25 | "'\"" 26 | ], 27 | "3": [ 28 | "2@", 29 | null, 30 | null, 31 | "4$", 32 | ".>", 33 | ",<" 34 | ], 35 | "4": [ 36 | "3#", 37 | null, 38 | null, 39 | "5%", 40 | "pP", 41 | ".>" 42 | ], 43 | "5": [ 44 | "4$", 45 | null, 46 | null, 47 | "6^", 48 | "yY", 49 | "pP" 50 | ], 51 | "6": [ 52 | "5%", 53 | null, 54 | null, 55 | "7&", 56 | "fF", 57 | "yY" 58 | ], 59 | "7": [ 60 | "6^", 61 | null, 62 | null, 63 | "8*", 64 | "gG", 65 | "fF" 66 | ], 67 | "8": [ 68 | "7&", 69 | null, 70 | null, 71 | "9(", 72 | "cC", 73 | "gG" 74 | ], 75 | "9": [ 76 | "8*", 77 | null, 78 | null, 79 | "0)", 80 | "rR", 81 | "cC" 82 | ], 83 | "!": [ 84 | "`~", 85 | null, 86 | null, 87 | "2@", 88 | "'\"", 89 | null 90 | ], 91 | "\"": [ 92 | null, 93 | "1!", 94 | "2@", 95 | ",<", 96 | "aA", 97 | null 98 | ], 99 | "#": [ 100 | "2@", 101 | null, 102 | null, 103 | "4$", 104 | ".>", 105 | ",<" 106 | ], 107 | "$": [ 108 | "3#", 109 | null, 110 | null, 111 | "5%", 112 | "pP", 113 | ".>" 114 | ], 115 | "%": [ 116 | "4$", 117 | null, 118 | null, 119 | "6^", 120 | "yY", 121 | "pP" 122 | ], 123 | "&": [ 124 | "6^", 125 | null, 126 | null, 127 | "8*", 128 | "gG", 129 | "fF" 130 | ], 131 | "'": [ 132 | null, 133 | "1!", 134 | "2@", 135 | ",<", 136 | "aA", 137 | null 138 | ], 139 | "(": [ 140 | "8*", 141 | null, 142 | null, 143 | "0)", 144 | "rR", 145 | "cC" 146 | ], 147 | ")": [ 148 | "9(", 149 | null, 150 | null, 151 | "[{", 152 | "lL", 153 | "rR" 154 | ], 155 | "*": [ 156 | "7&", 157 | null, 158 | null, 159 | "9(", 160 | "cC", 161 | "gG" 162 | ], 163 | "+": [ 164 | "/?", 165 | "]}", 166 | null, 167 | "\\|", 168 | null, 169 | "-_" 170 | ], 171 | ",": [ 172 | "'\"", 173 | "2@", 174 | "3#", 175 | ".>", 176 | "oO", 177 | "aA" 178 | ], 179 | "-": [ 180 | "sS", 181 | "/?", 182 | "=+", 183 | null, 184 | null, 185 | "zZ" 186 | ], 187 | ".": [ 188 | ",<", 189 | "3#", 190 | "4$", 191 | "pP", 192 | "eE", 193 | "oO" 194 | ], 195 | "/": [ 196 | "lL", 197 | "[{", 198 | "]}", 199 | "=+", 200 | "-_", 201 | "sS" 202 | ], 203 | ":": [ 204 | null, 205 | "aA", 206 | "oO", 207 | "qQ", 208 | null, 209 | null 210 | ], 211 | ";": [ 212 | null, 213 | "aA", 214 | "oO", 215 | "qQ", 216 | null, 217 | null 218 | ], 219 | "<": [ 220 | "'\"", 221 | "2@", 222 | "3#", 223 | ".>", 224 | "oO", 225 | "aA" 226 | ], 227 | "=": [ 228 | "/?", 229 | "]}", 230 | null, 231 | "\\|", 232 | null, 233 | "-_" 234 | ], 235 | ">": [ 236 | ",<", 237 | "3#", 238 | "4$", 239 | "pP", 240 | "eE", 241 | "oO" 242 | ], 243 | "?": [ 244 | "lL", 245 | "[{", 246 | "]}", 247 | "=+", 248 | "-_", 249 | "sS" 250 | ], 251 | "@": [ 252 | "1!", 253 | null, 254 | null, 255 | "3#", 256 | ",<", 257 | "'\"" 258 | ], 259 | "A": [ 260 | null, 261 | "'\"", 262 | ",<", 263 | "oO", 264 | ";:", 265 | null 266 | ], 267 | "B": [ 268 | "xX", 269 | "dD", 270 | "hH", 271 | "mM", 272 | null, 273 | null 274 | ], 275 | "C": [ 276 | "gG", 277 | "8*", 278 | "9(", 279 | "rR", 280 | "tT", 281 | "hH" 282 | ], 283 | "D": [ 284 | "iI", 285 | "fF", 286 | "gG", 287 | "hH", 288 | "bB", 289 | "xX" 290 | ], 291 | "E": [ 292 | "oO", 293 | ".>", 294 | "pP", 295 | "uU", 296 | "jJ", 297 | "qQ" 298 | ], 299 | "F": [ 300 | "yY", 301 | "6^", 302 | "7&", 303 | "gG", 304 | "dD", 305 | "iI" 306 | ], 307 | "G": [ 308 | "fF", 309 | "7&", 310 | "8*", 311 | "cC", 312 | "hH", 313 | "dD" 314 | ], 315 | "H": [ 316 | "dD", 317 | "gG", 318 | "cC", 319 | "tT", 320 | "mM", 321 | "bB" 322 | ], 323 | "I": [ 324 | "uU", 325 | "yY", 326 | "fF", 327 | "dD", 328 | "xX", 329 | "kK" 330 | ], 331 | "J": [ 332 | "qQ", 333 | "eE", 334 | "uU", 335 | "kK", 336 | null, 337 | null 338 | ], 339 | "K": [ 340 | "jJ", 341 | "uU", 342 | "iI", 343 | "xX", 344 | null, 345 | null 346 | ], 347 | "L": [ 348 | "rR", 349 | "0)", 350 | "[{", 351 | "/?", 352 | "sS", 353 | "nN" 354 | ], 355 | "M": [ 356 | "bB", 357 | "hH", 358 | "tT", 359 | "wW", 360 | null, 361 | null 362 | ], 363 | "N": [ 364 | "tT", 365 | "rR", 366 | "lL", 367 | "sS", 368 | "vV", 369 | "wW" 370 | ], 371 | "O": [ 372 | "aA", 373 | ",<", 374 | ".>", 375 | "eE", 376 | "qQ", 377 | ";:" 378 | ], 379 | "P": [ 380 | ".>", 381 | "4$", 382 | "5%", 383 | "yY", 384 | "uU", 385 | "eE" 386 | ], 387 | "Q": [ 388 | ";:", 389 | "oO", 390 | "eE", 391 | "jJ", 392 | null, 393 | null 394 | ], 395 | "R": [ 396 | "cC", 397 | "9(", 398 | "0)", 399 | "lL", 400 | "nN", 401 | "tT" 402 | ], 403 | "S": [ 404 | "nN", 405 | "lL", 406 | "/?", 407 | "-_", 408 | "zZ", 409 | "vV" 410 | ], 411 | "T": [ 412 | "hH", 413 | "cC", 414 | "rR", 415 | "nN", 416 | "wW", 417 | "mM" 418 | ], 419 | "U": [ 420 | "eE", 421 | "pP", 422 | "yY", 423 | "iI", 424 | "kK", 425 | "jJ" 426 | ], 427 | "V": [ 428 | "wW", 429 | "nN", 430 | "sS", 431 | "zZ", 432 | null, 433 | null 434 | ], 435 | "W": [ 436 | "mM", 437 | "tT", 438 | "nN", 439 | "vV", 440 | null, 441 | null 442 | ], 443 | "X": [ 444 | "kK", 445 | "iI", 446 | "dD", 447 | "bB", 448 | null, 449 | null 450 | ], 451 | "Y": [ 452 | "pP", 453 | "5%", 454 | "6^", 455 | "fF", 456 | "iI", 457 | "uU" 458 | ], 459 | "Z": [ 460 | "vV", 461 | "sS", 462 | "-_", 463 | null, 464 | null, 465 | null 466 | ], 467 | "[": [ 468 | "0)", 469 | null, 470 | null, 471 | "]}", 472 | "/?", 473 | "lL" 474 | ], 475 | "\\": [ 476 | "=+", 477 | null, 478 | null, 479 | null, 480 | null, 481 | null 482 | ], 483 | "]": [ 484 | "[{", 485 | null, 486 | null, 487 | null, 488 | "=+", 489 | "/?" 490 | ], 491 | "^": [ 492 | "5%", 493 | null, 494 | null, 495 | "7&", 496 | "fF", 497 | "yY" 498 | ], 499 | "_": [ 500 | "sS", 501 | "/?", 502 | "=+", 503 | null, 504 | null, 505 | "zZ" 506 | ], 507 | "`": [ 508 | null, 509 | null, 510 | null, 511 | "1!", 512 | null, 513 | null 514 | ], 515 | "a": [ 516 | null, 517 | "'\"", 518 | ",<", 519 | "oO", 520 | ";:", 521 | null 522 | ], 523 | "b": [ 524 | "xX", 525 | "dD", 526 | "hH", 527 | "mM", 528 | null, 529 | null 530 | ], 531 | "c": [ 532 | "gG", 533 | "8*", 534 | "9(", 535 | "rR", 536 | "tT", 537 | "hH" 538 | ], 539 | "d": [ 540 | "iI", 541 | "fF", 542 | "gG", 543 | "hH", 544 | "bB", 545 | "xX" 546 | ], 547 | "e": [ 548 | "oO", 549 | ".>", 550 | "pP", 551 | "uU", 552 | "jJ", 553 | "qQ" 554 | ], 555 | "f": [ 556 | "yY", 557 | "6^", 558 | "7&", 559 | "gG", 560 | "dD", 561 | "iI" 562 | ], 563 | "g": [ 564 | "fF", 565 | "7&", 566 | "8*", 567 | "cC", 568 | "hH", 569 | "dD" 570 | ], 571 | "h": [ 572 | "dD", 573 | "gG", 574 | "cC", 575 | "tT", 576 | "mM", 577 | "bB" 578 | ], 579 | "i": [ 580 | "uU", 581 | "yY", 582 | "fF", 583 | "dD", 584 | "xX", 585 | "kK" 586 | ], 587 | "j": [ 588 | "qQ", 589 | "eE", 590 | "uU", 591 | "kK", 592 | null, 593 | null 594 | ], 595 | "k": [ 596 | "jJ", 597 | "uU", 598 | "iI", 599 | "xX", 600 | null, 601 | null 602 | ], 603 | "l": [ 604 | "rR", 605 | "0)", 606 | "[{", 607 | "/?", 608 | "sS", 609 | "nN" 610 | ], 611 | "m": [ 612 | "bB", 613 | "hH", 614 | "tT", 615 | "wW", 616 | null, 617 | null 618 | ], 619 | "n": [ 620 | "tT", 621 | "rR", 622 | "lL", 623 | "sS", 624 | "vV", 625 | "wW" 626 | ], 627 | "o": [ 628 | "aA", 629 | ",<", 630 | ".>", 631 | "eE", 632 | "qQ", 633 | ";:" 634 | ], 635 | "p": [ 636 | ".>", 637 | "4$", 638 | "5%", 639 | "yY", 640 | "uU", 641 | "eE" 642 | ], 643 | "q": [ 644 | ";:", 645 | "oO", 646 | "eE", 647 | "jJ", 648 | null, 649 | null 650 | ], 651 | "r": [ 652 | "cC", 653 | "9(", 654 | "0)", 655 | "lL", 656 | "nN", 657 | "tT" 658 | ], 659 | "s": [ 660 | "nN", 661 | "lL", 662 | "/?", 663 | "-_", 664 | "zZ", 665 | "vV" 666 | ], 667 | "t": [ 668 | "hH", 669 | "cC", 670 | "rR", 671 | "nN", 672 | "wW", 673 | "mM" 674 | ], 675 | "u": [ 676 | "eE", 677 | "pP", 678 | "yY", 679 | "iI", 680 | "kK", 681 | "jJ" 682 | ], 683 | "v": [ 684 | "wW", 685 | "nN", 686 | "sS", 687 | "zZ", 688 | null, 689 | null 690 | ], 691 | "w": [ 692 | "mM", 693 | "tT", 694 | "nN", 695 | "vV", 696 | null, 697 | null 698 | ], 699 | "x": [ 700 | "kK", 701 | "iI", 702 | "dD", 703 | "bB", 704 | null, 705 | null 706 | ], 707 | "y": [ 708 | "pP", 709 | "5%", 710 | "6^", 711 | "fF", 712 | "iI", 713 | "uU" 714 | ], 715 | "z": [ 716 | "vV", 717 | "sS", 718 | "-_", 719 | null, 720 | null, 721 | null 722 | ], 723 | "{": [ 724 | "0)", 725 | null, 726 | null, 727 | "]}", 728 | "/?", 729 | "lL" 730 | ], 731 | "|": [ 732 | "=+", 733 | null, 734 | null, 735 | null, 736 | null, 737 | null 738 | ], 739 | "}": [ 740 | "[{", 741 | null, 742 | null, 743 | null, 744 | "=+", 745 | "/?" 746 | ], 747 | "~": [ 748 | null, 749 | null, 750 | null, 751 | "1!", 752 | null, 753 | null 754 | ] 755 | } 756 | } 757 | -------------------------------------------------------------------------------- /data/data/Keypad.json: -------------------------------------------------------------------------------- 1 | { 2 | "Graph": { 3 | "0": [ 4 | null, 5 | "1", 6 | "2", 7 | "3", 8 | ".", 9 | null, 10 | null, 11 | null 12 | ], 13 | "1": [ 14 | null, 15 | null, 16 | "4", 17 | "5", 18 | "2", 19 | "0", 20 | null, 21 | null 22 | ], 23 | "2": [ 24 | "1", 25 | "4", 26 | "5", 27 | "6", 28 | "3", 29 | ".", 30 | "0", 31 | null 32 | ], 33 | "3": [ 34 | "2", 35 | "5", 36 | "6", 37 | null, 38 | null, 39 | null, 40 | ".", 41 | "0" 42 | ], 43 | "4": [ 44 | null, 45 | null, 46 | "7", 47 | "8", 48 | "5", 49 | "2", 50 | "1", 51 | null 52 | ], 53 | "5": [ 54 | "4", 55 | "7", 56 | "8", 57 | "9", 58 | "6", 59 | "3", 60 | "2", 61 | "1" 62 | ], 63 | "6": [ 64 | "5", 65 | "8", 66 | "9", 67 | "+", 68 | null, 69 | null, 70 | "3", 71 | "2" 72 | ], 73 | "7": [ 74 | null, 75 | null, 76 | null, 77 | "/", 78 | "8", 79 | "5", 80 | "4", 81 | null 82 | ], 83 | "8": [ 84 | "7", 85 | null, 86 | "/", 87 | "*", 88 | "9", 89 | "6", 90 | "5", 91 | "4" 92 | ], 93 | "9": [ 94 | "8", 95 | "/", 96 | "*", 97 | "-", 98 | "+", 99 | null, 100 | "6", 101 | "5" 102 | ], 103 | "*": [ 104 | "/", 105 | null, 106 | null, 107 | null, 108 | "-", 109 | "+", 110 | "9", 111 | "8" 112 | ], 113 | "+": [ 114 | "9", 115 | "*", 116 | "-", 117 | null, 118 | null, 119 | null, 120 | null, 121 | "6" 122 | ], 123 | "-": [ 124 | "*", 125 | null, 126 | null, 127 | null, 128 | null, 129 | null, 130 | "+", 131 | "9" 132 | ], 133 | ".": [ 134 | "0", 135 | "2", 136 | "3", 137 | null, 138 | null, 139 | null, 140 | null, 141 | null 142 | ], 143 | "/": [ 144 | null, 145 | null, 146 | null, 147 | null, 148 | "*", 149 | "9", 150 | "8", 151 | "7" 152 | ] 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /data/data/L33t.json: -------------------------------------------------------------------------------- 1 | { 2 | "graph": { 3 | "a": [ 4 | "4", 5 | "@" 6 | ], 7 | "b": [ 8 | "8" 9 | ], 10 | "c": [ 11 | "(", 12 | "{", 13 | "[", 14 | "<" 15 | ], 16 | "e": [ 17 | "3" 18 | ], 19 | "g": [ 20 | "6", 21 | "9" 22 | ], 23 | "i": [ 24 | "1", 25 | "!", 26 | "|" 27 | ], 28 | "l": [ 29 | "1", 30 | "|", 31 | "7" 32 | ], 33 | "o": [ 34 | "0" 35 | ], 36 | "s": [ 37 | "$", 38 | "5" 39 | ], 40 | "t": [ 41 | "+", 42 | "7" 43 | ], 44 | "x": [ 45 | "%" 46 | ], 47 | "z": [ 48 | "2" 49 | ] 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /data/data/MacKeypad.json: -------------------------------------------------------------------------------- 1 | { 2 | "Graph": { 3 | "0": [ 4 | null, 5 | "1", 6 | "2", 7 | "3", 8 | ".", 9 | null, 10 | null, 11 | null 12 | ], 13 | "1": [ 14 | null, 15 | null, 16 | "4", 17 | "5", 18 | "2", 19 | "0", 20 | null, 21 | null 22 | ], 23 | "2": [ 24 | "1", 25 | "4", 26 | "5", 27 | "6", 28 | "3", 29 | ".", 30 | "0", 31 | null 32 | ], 33 | "3": [ 34 | "2", 35 | "5", 36 | "6", 37 | "+", 38 | null, 39 | null, 40 | ".", 41 | "0" 42 | ], 43 | "4": [ 44 | null, 45 | null, 46 | "7", 47 | "8", 48 | "5", 49 | "2", 50 | "1", 51 | null 52 | ], 53 | "5": [ 54 | "4", 55 | "7", 56 | "8", 57 | "9", 58 | "6", 59 | "3", 60 | "2", 61 | "1" 62 | ], 63 | "6": [ 64 | "5", 65 | "8", 66 | "9", 67 | "-", 68 | "+", 69 | null, 70 | "3", 71 | "2" 72 | ], 73 | "7": [ 74 | null, 75 | null, 76 | null, 77 | "=", 78 | "8", 79 | "5", 80 | "4", 81 | null 82 | ], 83 | "8": [ 84 | "7", 85 | null, 86 | "=", 87 | "/", 88 | "9", 89 | "6", 90 | "5", 91 | "4" 92 | ], 93 | "9": [ 94 | "8", 95 | "=", 96 | "/", 97 | "*", 98 | "-", 99 | "+", 100 | "6", 101 | "5" 102 | ], 103 | "*": [ 104 | "/", 105 | null, 106 | null, 107 | null, 108 | null, 109 | null, 110 | "-", 111 | "9" 112 | ], 113 | "+": [ 114 | "6", 115 | "9", 116 | "-", 117 | null, 118 | null, 119 | null, 120 | null, 121 | "3" 122 | ], 123 | "-": [ 124 | "9", 125 | "/", 126 | "*", 127 | null, 128 | null, 129 | null, 130 | "+", 131 | "6" 132 | ], 133 | ".": [ 134 | "0", 135 | "2", 136 | "3", 137 | null, 138 | null, 139 | null, 140 | null, 141 | null 142 | ], 143 | "/": [ 144 | "=", 145 | null, 146 | null, 147 | null, 148 | "*", 149 | "-", 150 | "9", 151 | "8" 152 | ], 153 | "=": [ 154 | null, 155 | null, 156 | null, 157 | null, 158 | "/", 159 | "9", 160 | "8", 161 | "7" 162 | ] 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /data/data/MaleNames.json: -------------------------------------------------------------------------------- 1 | {"List":[ 2 | "james", 3 | "john", 4 | "robert", 5 | "michael", 6 | "william", 7 | "david", 8 | "richard", 9 | "charles", 10 | "joseph", 11 | "thomas", 12 | "christopher", 13 | "daniel", 14 | "paul", 15 | "mark", 16 | "donald", 17 | "george", 18 | "kenneth", 19 | "steven", 20 | "edward", 21 | "brian", 22 | "ronald", 23 | "anthony", 24 | "kevin", 25 | "jason", 26 | "matthew", 27 | "gary", 28 | "timothy", 29 | "jose", 30 | "larry", 31 | "jeffrey", 32 | "frank", 33 | "scott", 34 | "eric", 35 | "stephen", 36 | "andrew", 37 | "raymond", 38 | "gregory", 39 | "joshua", 40 | "jerry", 41 | "dennis", 42 | "walter", 43 | "patrick", 44 | "peter", 45 | "harold", 46 | "douglas", 47 | "henry", 48 | "carl", 49 | "arthur", 50 | "ryan", 51 | "roger", 52 | "joe", 53 | "juan", 54 | "jack", 55 | "albert", 56 | "jonathan", 57 | "justin", 58 | "terry", 59 | "gerald", 60 | "keith", 61 | "samuel", 62 | "willie", 63 | "ralph", 64 | "lawrence", 65 | "nicholas", 66 | "roy", 67 | "benjamin", 68 | "bruce", 69 | "brandon", 70 | "adam", 71 | "harry", 72 | "fred", 73 | "wayne", 74 | "billy", 75 | "steve", 76 | "louis", 77 | "jeremy", 78 | "aaron", 79 | "randy", 80 | "eugene", 81 | "carlos", 82 | "russell", 83 | "bobby", 84 | "victor", 85 | "ernest", 86 | "phillip", 87 | "todd", 88 | "jesse", 89 | "craig", 90 | "alan", 91 | "shawn", 92 | "clarence", 93 | "sean", 94 | "philip", 95 | "chris", 96 | "johnny", 97 | "earl", 98 | "jimmy", 99 | "antonio", 100 | "danny", 101 | "bryan", 102 | "tony", 103 | "luis", 104 | "mike", 105 | "stanley", 106 | "leonard", 107 | "nathan", 108 | "dale", 109 | "manuel", 110 | "rodney", 111 | "curtis", 112 | "norman", 113 | "marvin", 114 | "vincent", 115 | "glenn", 116 | "jeffery", 117 | "travis", 118 | "jeff", 119 | "chad", 120 | "jacob", 121 | "melvin", 122 | "alfred", 123 | "kyle", 124 | "francis", 125 | "bradley", 126 | "jesus", 127 | "herbert", 128 | "frederick", 129 | "ray", 130 | "joel", 131 | "edwin", 132 | "don", 133 | "eddie", 134 | "ricky", 135 | "troy", 136 | "randall", 137 | "barry", 138 | "bernard", 139 | "mario", 140 | "leroy", 141 | "francisco", 142 | "marcus", 143 | "micheal", 144 | "theodore", 145 | "clifford", 146 | "miguel", 147 | "oscar", 148 | "jay", 149 | "jim", 150 | "tom", 151 | "calvin", 152 | "alex", 153 | "jon", 154 | "ronnie", 155 | "bill", 156 | "lloyd", 157 | "tommy", 158 | "leon", 159 | "derek", 160 | "darrell", 161 | "jerome", 162 | "floyd", 163 | "leo", 164 | "alvin", 165 | "tim", 166 | "wesley", 167 | "dean", 168 | "greg", 169 | "jorge", 170 | "dustin", 171 | "pedro", 172 | "derrick", 173 | "dan", 174 | "zachary", 175 | "corey", 176 | "herman", 177 | "maurice", 178 | "vernon", 179 | "roberto", 180 | "clyde", 181 | "glen", 182 | "hector", 183 | "shane", 184 | "ricardo", 185 | "sam", 186 | "rick", 187 | "lester", 188 | "brent", 189 | "ramon", 190 | "tyler", 191 | "gilbert", 192 | "gene", 193 | "marc", 194 | "reginald", 195 | "ruben", 196 | "brett", 197 | "angel", 198 | "nathaniel", 199 | "rafael", 200 | "edgar", 201 | "milton", 202 | "raul", 203 | "ben", 204 | "cecil", 205 | "duane", 206 | "andre", 207 | "elmer", 208 | "brad", 209 | "gabriel", 210 | "ron", 211 | "roland", 212 | "jared", 213 | "adrian", 214 | "karl", 215 | "cory", 216 | "claude", 217 | "erik", 218 | "darryl", 219 | "neil", 220 | "christian", 221 | "javier", 222 | "fernando", 223 | "clinton", 224 | "ted", 225 | "mathew", 226 | "tyrone", 227 | "darren", 228 | "lonnie", 229 | "lance", 230 | "cody", 231 | "julio", 232 | "kurt", 233 | "allan", 234 | "clayton", 235 | "hugh", 236 | "max", 237 | "dwayne", 238 | "dwight", 239 | "armando", 240 | "felix", 241 | "jimmie", 242 | "everett", 243 | "ian", 244 | "ken", 245 | "bob", 246 | "jaime", 247 | "casey", 248 | "alfredo", 249 | "alberto", 250 | "dave", 251 | "ivan", 252 | "johnnie", 253 | "sidney", 254 | "byron", 255 | "julian", 256 | "isaac", 257 | "clifton", 258 | "willard", 259 | "daryl", 260 | "virgil", 261 | "andy", 262 | "salvador", 263 | "kirk", 264 | "sergio", 265 | "seth", 266 | "kent", 267 | "terrance", 268 | "rene", 269 | "eduardo", 270 | "terrence", 271 | "enrique", 272 | "freddie", 273 | "stuart", 274 | "fredrick", 275 | "arturo", 276 | "alejandro", 277 | "joey", 278 | "nick", 279 | "luther", 280 | "wendell", 281 | "jeremiah", 282 | "evan", 283 | "julius", 284 | "donnie", 285 | "otis", 286 | "trevor", 287 | "luke", 288 | "homer", 289 | "gerard", 290 | "doug", 291 | "kenny", 292 | "hubert", 293 | "angelo", 294 | "shaun", 295 | "lyle", 296 | "matt", 297 | "alfonso", 298 | "orlando", 299 | "rex", 300 | "carlton", 301 | "ernesto", 302 | "pablo", 303 | "lorenzo", 304 | "omar", 305 | "wilbur", 306 | "blake", 307 | "horace", 308 | "roderick", 309 | "kerry", 310 | "abraham", 311 | "rickey", 312 | "ira", 313 | "andres", 314 | "cesar", 315 | "johnathan", 316 | "malcolm", 317 | "rudolph", 318 | "damon", 319 | "kelvin", 320 | "rudy", 321 | "preston", 322 | "alton", 323 | "archie", 324 | "marco", 325 | "wm", 326 | "pete", 327 | "randolph", 328 | "garry", 329 | "geoffrey", 330 | "jonathon", 331 | "felipe", 332 | "bennie", 333 | "gerardo", 334 | "ed", 335 | "dominic", 336 | "loren", 337 | "delbert", 338 | "colin", 339 | "guillermo", 340 | "earnest", 341 | "benny", 342 | "noel", 343 | "rodolfo", 344 | "myron", 345 | "edmund", 346 | "salvatore", 347 | "cedric", 348 | "lowell", 349 | "gregg", 350 | "sherman", 351 | "devin", 352 | "sylvester", 353 | "roosevelt", 354 | "israel", 355 | "jermaine", 356 | "forrest", 357 | "wilbert", 358 | "leland", 359 | "simon", 360 | "irving", 361 | "owen", 362 | "rufus", 363 | "woodrow", 364 | "kristopher", 365 | "levi", 366 | "marcos", 367 | "gustavo", 368 | "lionel", 369 | "marty", 370 | "gilberto", 371 | "clint", 372 | "nicolas", 373 | "laurence", 374 | "ismael", 375 | "orville", 376 | "drew", 377 | "ervin", 378 | "dewey", 379 | "al", 380 | "wilfred", 381 | "josh", 382 | "hugo", 383 | "ignacio", 384 | "caleb", 385 | "tomas", 386 | "sheldon", 387 | "erick", 388 | "frankie", 389 | "darrel", 390 | "rogelio", 391 | "terence", 392 | "alonzo", 393 | "elias", 394 | "bert", 395 | "elbert", 396 | "ramiro", 397 | "conrad", 398 | "noah", 399 | "grady", 400 | "phil", 401 | "cornelius", 402 | "lamar", 403 | "rolando", 404 | "clay", 405 | "percy", 406 | "dexter", 407 | "bradford", 408 | "merle", 409 | "darin", 410 | "amos", 411 | "terrell", 412 | "moses", 413 | "irvin", 414 | "saul", 415 | "roman", 416 | "darnell", 417 | "randal", 418 | "tommie", 419 | "timmy", 420 | "darrin", 421 | "brendan", 422 | "toby", 423 | "van", 424 | "abel", 425 | "dominick", 426 | "emilio", 427 | "elijah", 428 | "cary", 429 | "domingo", 430 | "aubrey", 431 | "emmett", 432 | "marlon", 433 | "emanuel", 434 | "jerald", 435 | "edmond", 436 | "emil", 437 | "dewayne", 438 | "otto", 439 | "teddy", 440 | "reynaldo", 441 | "bret", 442 | "jess", 443 | "trent", 444 | "humberto", 445 | "emmanuel", 446 | "stephan", 447 | "louie", 448 | "vicente", 449 | "lamont", 450 | "garland", 451 | "micah", 452 | "efrain", 453 | "heath", 454 | "rodger", 455 | "demetrius", 456 | "ethan", 457 | "eldon", 458 | "rocky", 459 | "pierre", 460 | "eli", 461 | "bryce", 462 | "antoine", 463 | "robbie", 464 | "kendall", 465 | "royce", 466 | "sterling", 467 | "grover", 468 | "elton", 469 | "cleveland", 470 | "dylan", 471 | "chuck", 472 | "damian", 473 | "reuben", 474 | "stan", 475 | "leonardo", 476 | "russel", 477 | "erwin", 478 | "benito", 479 | "hans", 480 | "monte", 481 | "blaine", 482 | "ernie", 483 | "curt", 484 | "quentin", 485 | "agustin", 486 | "jamal", 487 | "devon", 488 | "adolfo", 489 | "tyson", 490 | "wilfredo", 491 | "bart", 492 | "jarrod", 493 | "vance", 494 | "denis", 495 | "damien", 496 | "joaquin", 497 | "harlan", 498 | "desmond", 499 | "elliot", 500 | "darwin", 501 | "gregorio", 502 | "kermit", 503 | "roscoe", 504 | "esteban", 505 | "anton", 506 | "solomon", 507 | "norbert", 508 | "elvin", 509 | "nolan", 510 | "carey", 511 | "rod", 512 | "quinton", 513 | "hal", 514 | "brain", 515 | "rob", 516 | "elwood", 517 | "kendrick", 518 | "darius", 519 | "moises", 520 | "marlin", 521 | "fidel", 522 | "thaddeus", 523 | "cliff", 524 | "marcel", 525 | "ali", 526 | "raphael", 527 | "bryon", 528 | "armand", 529 | "alvaro", 530 | "jeffry", 531 | "dane", 532 | "joesph", 533 | "thurman", 534 | "ned", 535 | "sammie", 536 | "rusty", 537 | "michel", 538 | "monty", 539 | "rory", 540 | "fabian", 541 | "reggie", 542 | "kris", 543 | "isaiah", 544 | "gus", 545 | "avery", 546 | "loyd", 547 | "diego", 548 | "adolph", 549 | "millard", 550 | "rocco", 551 | "gonzalo", 552 | "derick", 553 | "rodrigo", 554 | "gerry", 555 | "rigoberto", 556 | "alphonso", 557 | "ty", 558 | "rickie", 559 | "noe", 560 | "vern", 561 | "elvis", 562 | "bernardo", 563 | "mauricio", 564 | "hiram", 565 | "donovan", 566 | "basil", 567 | "nickolas", 568 | "scot", 569 | "vince", 570 | "quincy", 571 | "eddy", 572 | "sebastian", 573 | "federico", 574 | "ulysses", 575 | "heriberto", 576 | "donnell", 577 | "denny", 578 | "gavin", 579 | "emery", 580 | "romeo", 581 | "jayson", 582 | "dion", 583 | "dante", 584 | "clement", 585 | "coy", 586 | "odell", 587 | "jarvis", 588 | "bruno", 589 | "issac", 590 | "dudley", 591 | "sanford", 592 | "colby", 593 | "carmelo", 594 | "nestor", 595 | "hollis", 596 | "stefan", 597 | "donny", 598 | "art", 599 | "linwood", 600 | "beau", 601 | "weldon", 602 | "galen", 603 | "isidro", 604 | "truman", 605 | "delmar", 606 | "johnathon", 607 | "silas", 608 | "frederic", 609 | "irwin", 610 | "merrill", 611 | "charley", 612 | "marcelino", 613 | "carlo", 614 | "trenton", 615 | "kurtis", 616 | "aurelio", 617 | "winfred", 618 | "vito", 619 | "collin", 620 | "denver", 621 | "leonel", 622 | "emory", 623 | "pasquale", 624 | "mohammad", 625 | "mariano", 626 | "danial", 627 | "landon", 628 | "dirk", 629 | "branden", 630 | "adan", 631 | "numbers", 632 | "clair", 633 | "buford", 634 | "german", 635 | "bernie", 636 | "wilmer", 637 | "emerson", 638 | "zachery", 639 | "jacques", 640 | "errol", 641 | "josue", 642 | "edwardo", 643 | "wilford", 644 | "theron", 645 | "raymundo", 646 | "daren", 647 | "tristan", 648 | "robby", 649 | "lincoln", 650 | "jame", 651 | "genaro", 652 | "octavio", 653 | "cornell", 654 | "hung", 655 | "arron", 656 | "antony", 657 | "herschel", 658 | "alva", 659 | "giovanni", 660 | "garth", 661 | "cyrus", 662 | "cyril", 663 | "ronny", 664 | "stevie", 665 | "lon", 666 | "kennith", 667 | "carmine", 668 | "augustine", 669 | "erich", 670 | "chadwick", 671 | "wilburn", 672 | "russ", 673 | "myles", 674 | "jonas", 675 | "mitchel", 676 | "mervin", 677 | "zane", 678 | "jamel", 679 | "lazaro", 680 | "alphonse", 681 | "randell", 682 | "major", 683 | "johnie", 684 | "jarrett", 685 | "ariel", 686 | "abdul", 687 | "dusty", 688 | "luciano", 689 | "seymour", 690 | "scottie", 691 | "eugenio", 692 | "mohammed", 693 | "valentin", 694 | "arnulfo", 695 | "lucien", 696 | "ferdinand", 697 | "thad", 698 | "ezra", 699 | "aldo", 700 | "rubin", 701 | "royal", 702 | "mitch", 703 | "earle", 704 | "abe", 705 | "marquis", 706 | "lanny", 707 | "kareem", 708 | "jamar", 709 | "boris", 710 | "isiah", 711 | "emile", 712 | "elmo", 713 | "aron", 714 | "leopoldo", 715 | "everette", 716 | "josef", 717 | "eloy", 718 | "dorian", 719 | "rodrick", 720 | "reinaldo", 721 | "lucio", 722 | "jerrod", 723 | "weston", 724 | "hershel", 725 | "lemuel", 726 | "lavern", 727 | "burt", 728 | "jules", 729 | "gil", 730 | "eliseo", 731 | "ahmad", 732 | "nigel", 733 | "efren", 734 | "antwan", 735 | "alden", 736 | "margarito", 737 | "refugio", 738 | "dino", 739 | "osvaldo", 740 | "les", 741 | "deandre", 742 | "normand", 743 | "kieth", 744 | "ivory", 745 | "trey", 746 | "norberto", 747 | "napoleon", 748 | "jerold", 749 | "fritz", 750 | "rosendo", 751 | "milford", 752 | "sang", 753 | "deon", 754 | "christoper", 755 | "alfonzo", 756 | "lyman", 757 | "josiah", 758 | "brant", 759 | "wilton", 760 | "rico", 761 | "jamaal", 762 | "dewitt", 763 | "brenton", 764 | "yong", 765 | "olin", 766 | "faustino", 767 | "claudio", 768 | "judson", 769 | "gino", 770 | "edgardo", 771 | "alec", 772 | "jarred", 773 | "donn", 774 | "trinidad", 775 | "tad", 776 | "porfirio", 777 | "odis", 778 | "lenard", 779 | "chauncey", 780 | "tod", 781 | "mel", 782 | "marcelo", 783 | "kory", 784 | "augustus", 785 | "keven", 786 | "hilario", 787 | "bud", 788 | "sal", 789 | "orval", 790 | "mauro", 791 | "dannie", 792 | "zachariah", 793 | "olen", 794 | "anibal", 795 | "milo", 796 | "jed", 797 | "thanh", 798 | "amado", 799 | "lenny", 800 | "tory", 801 | "richie", 802 | "horacio", 803 | "brice", 804 | "mohamed", 805 | "delmer", 806 | "dario", 807 | "mac", 808 | "jonah", 809 | "jerrold", 810 | "robt", 811 | "hank", 812 | "sung", 813 | "rupert", 814 | "rolland", 815 | "kenton", 816 | "damion", 817 | "chi", 818 | "antone", 819 | "waldo", 820 | "fredric", 821 | "bradly", 822 | "kip", 823 | "burl", 824 | "tyree", 825 | "jefferey", 826 | "ahmed", 827 | "willy", 828 | "stanford", 829 | "oren", 830 | "moshe", 831 | "mikel", 832 | "enoch", 833 | "brendon", 834 | "quintin", 835 | "jamison", 836 | "florencio", 837 | "darrick", 838 | "tobias", 839 | "minh", 840 | "hassan", 841 | "giuseppe", 842 | "demarcus", 843 | "cletus", 844 | "tyrell", 845 | "lyndon", 846 | "keenan", 847 | "werner", 848 | "theo", 849 | "geraldo", 850 | "columbus", 851 | "chet", 852 | "bertram", 853 | "markus", 854 | "huey", 855 | "hilton", 856 | "dwain", 857 | "donte", 858 | "tyron", 859 | "omer", 860 | "isaias", 861 | "hipolito", 862 | "fermin", 863 | "chung", 864 | "adalberto", 865 | "jamey", 866 | "teodoro", 867 | "mckinley", 868 | "maximo", 869 | "sol", 870 | "raleigh", 871 | "lawerence", 872 | "abram", 873 | "rashad", 874 | "emmitt", 875 | "daron", 876 | "chong", 877 | "samual", 878 | "otha", 879 | "miquel", 880 | "eusebio", 881 | "dong", 882 | "domenic", 883 | "darron", 884 | "wilber", 885 | "renato", 886 | "hoyt", 887 | "haywood", 888 | "ezekiel", 889 | "chas", 890 | "florentino", 891 | "elroy", 892 | "clemente", 893 | "arden", 894 | "neville", 895 | "edison", 896 | "deshawn", 897 | "carrol", 898 | "shayne", 899 | "nathanial", 900 | "jordon", 901 | "danilo", 902 | "claud", 903 | "val", 904 | "sherwood", 905 | "raymon", 906 | "rayford", 907 | "cristobal", 908 | "ambrose", 909 | "titus", 910 | "hyman", 911 | "felton", 912 | "ezequiel", 913 | "erasmo", 914 | "lonny", 915 | "len", 916 | "ike", 917 | "milan", 918 | "lino", 919 | "jarod", 920 | "herb", 921 | "andreas", 922 | "rhett", 923 | "jude", 924 | "douglass", 925 | "cordell", 926 | "oswaldo", 927 | "ellsworth", 928 | "virgilio", 929 | "toney", 930 | "nathanael", 931 | "del", 932 | "benedict", 933 | "mose", 934 | "hong", 935 | "isreal", 936 | "garret", 937 | "fausto", 938 | "asa", 939 | "arlen", 940 | "zack", 941 | "modesto", 942 | "francesco", 943 | "manual", 944 | "jae", 945 | "gaylord", 946 | "gaston", 947 | "filiberto", 948 | "deangelo", 949 | "michale", 950 | "granville", 951 | "wes", 952 | "malik", 953 | "zackary", 954 | "tuan", 955 | "nicky", 956 | "cristopher", 957 | "antione", 958 | "malcom", 959 | "korey", 960 | "jospeh", 961 | "colton", 962 | "waylon", 963 | "von", 964 | "hosea", 965 | "shad", 966 | "santo", 967 | "rudolf", 968 | "rolf", 969 | "rey", 970 | "renaldo", 971 | "marcellus", 972 | "lucius", 973 | "kristofer", 974 | "harland", 975 | "arnoldo", 976 | "rueben", 977 | "leandro", 978 | "kraig", 979 | "jerrell", 980 | "jeromy", 981 | "hobert", 982 | "cedrick", 983 | "arlie", 984 | "winford", 985 | "wally", 986 | "luigi", 987 | "keneth", 988 | "jacinto", 989 | "graig", 990 | "franklyn", 991 | "edmundo", 992 | "sid", 993 | "leif", 994 | "jeramy", 995 | "willian", 996 | "vincenzo", 997 | "shon", 998 | "michal", 999 | "lynwood", 1000 | "jere", 1001 | "hai", 1002 | "elden", 1003 | "darell", 1004 | "broderick", 1005 | "alonso" 1006 | ]} 1007 | -------------------------------------------------------------------------------- /data/data/Passwords.json: -------------------------------------------------------------------------------- 1 | {"List":["password","123456","12345678","1234","qwerty","12345","dragon","pussy","baseball","football","letmein","monkey","696969","abc123","mustang","shadow","master","111111","2000","jordan","superman","harley","1234567","fuckme","hunter","fuckyou","trustno1","ranger","buster","tigger","soccer","fuck","batman","test","pass","killer","hockey","charlie","love","sunshine","asshole","6969","pepper","access","123456789","654321","maggie","starwars","silver","dallas","yankees","123123","666666","hello","orange","biteme","freedom","computer","sexy","thunder","ginger","hammer","summer","corvette","fucker","austin","1111","merlin","121212","golfer","cheese","princess","chelsea","diamond","yellow","bigdog","secret","asdfgh","sparky","cowboy","camaro","matrix","falcon","iloveyou","guitar","purple","scooter","phoenix","aaaaaa","tigers","porsche","mickey","maverick","cookie","nascar","peanut","131313","money","horny","samantha","panties","steelers","snoopy","boomer","whatever","iceman","smokey","gateway","dakota","cowboys","eagles","chicken","dick","black","zxcvbn","ferrari","knight","hardcore","compaq","coffee","booboo","bitch","bulldog","xxxxxx","welcome","player","ncc1701","wizard","scooby","junior","internet","bigdick","brandy","tennis","blowjob","banana","monster","spider","lakers","rabbit","enter","mercedes","fender","yamaha","diablo","boston","tiger","marine","chicago","rangers","gandalf","winter","bigtits","barney","raiders","porn","badboy","blowme","spanky","bigdaddy","chester","london","midnight","blue","fishing","000000","hannah","slayer","11111111","sexsex","redsox","thx1138","asdf","marlboro","panther","zxcvbnm","arsenal","qazwsx","mother","7777777","jasper","winner","golden","butthead","viking","iwantu","angels","prince","cameron","girls","madison","hooters","startrek","captain","maddog","jasmine","butter","booger","golf","rocket","theman","liverpoo","flower","forever","muffin","turtle","sophie","redskins","toyota","sierra","winston","giants","packers","newyork","casper","bubba","112233","lovers","mountain","united","driver","helpme","fucking","pookie","lucky","maxwell","8675309","bear","suckit","gators","5150","222222","shithead","fuckoff","jaguar","hotdog","tits","gemini","lover","xxxxxxxx","777777","canada","florida","88888888","rosebud","metallic","doctor","trouble","success","stupid","tomcat","warrior","peaches","apples","fish","qwertyui","magic","buddy","dolphins","rainbow","gunner","987654","freddy","alexis","braves","cock","2112","1212","cocacola","xavier","dolphin","testing","bond007","member","voodoo","7777","samson","apollo","fire","tester","beavis","voyager","porno","rush2112","beer","apple","scorpio","skippy","sydney","red123","power","beaver","star","jackass","flyers","boobs","232323","zzzzzz","scorpion","doggie","legend","ou812","yankee","blazer","runner","birdie","bitches","555555","topgun","asdfasdf","heaven","viper","animal","2222","bigboy","4444","private","godzilla","lifehack","phantom","rock","august","sammy","cool","platinum","jake","bronco","heka6w2","copper","cumshot","garfield","willow","cunt","slut","69696969","kitten","super","jordan23","eagle1","shelby","america","11111","free","123321","chevy","bullshit","broncos","horney","surfer","nissan","999999","saturn","airborne","elephant","shit","action","adidas","qwert","1313","explorer","police","christin","december","wolf","sweet","therock","online","dickhead","brooklyn","cricket","racing","penis","0000","teens","redwings","dreams","michigan","hentai","magnum","87654321","donkey","trinity","digital","333333","cartman","guinness","123abc","speedy","buffalo","kitty","pimpin","eagle","einstein","nirvana","vampire","xxxx","playboy","pumpkin","snowball","test123","sucker","mexico","beatles","fantasy","celtic","cherry","cassie","888888","sniper","genesis","hotrod","reddog","alexande","college","jester","passw0rd","bigcock","lasvegas","slipknot","3333","death","1q2w3e","eclipse","1q2w3e4r","drummer","montana","music","aaaa","carolina","colorado","creative","hello1","goober","friday","bollocks","scotty","abcdef","bubbles","hawaii","fluffy","horses","thumper","5555","pussies","darkness","asdfghjk","boobies","buddha","sandman","naughty","honda","azerty","6666","shorty","money1","beach","loveme","4321","simple","poohbear","444444","badass","destiny","vikings","lizard","assman","nintendo","123qwe","november","xxxxx","october","leather","bastard","101010","extreme","password1","pussy1","lacrosse","hotmail","spooky","amateur","alaska","badger","paradise","maryjane","poop","mozart","video","vagina","spitfire","cherokee","cougar","420420","horse","enigma","raider","brazil","blonde","55555","dude","drowssap","lovely","1qaz2wsx","booty","snickers","nipples","diesel","rocks","eminem","westside","suzuki","passion","hummer","ladies","alpha","suckme","147147","pirate","semperfi","jupiter","redrum","freeuser","wanker","stinky","ducati","paris","babygirl","windows","spirit","pantera","monday","patches","brutus","smooth","penguin","marley","forest","cream","212121","flash","maximus","nipple","vision","pokemon","champion","fireman","indian","softball","picard","system","cobra","enjoy","lucky1","boogie","marines","security","dirty","admin","wildcats","pimp","dancer","hardon","fucked","abcd1234","abcdefg","ironman","wolverin","freepass","bigred","squirt","justice","hobbes","pearljam","mercury","domino","9999","rascal","hitman","mistress","bbbbbb","peekaboo","naked","budlight","electric","sluts","stargate","saints","bondage","bigman","zombie","swimming","duke","qwerty1","babes","scotland","disney","rooster","mookie","swordfis","hunting","blink182","8888","samsung","bubba1","whore","general","passport","aaaaaaaa","erotic","liberty","arizona","abcd","newport","skipper","rolltide","balls","happy1","galore","christ","weasel","242424","wombat","digger","classic","bulldogs","poopoo","accord","popcorn","turkey","bunny","mouse","007007","titanic","liverpool","dreamer","everton","chevelle","psycho","nemesis","pontiac","connor","eatme","lickme","cumming","ireland","spiderma","patriots","goblue","devils","empire","asdfg","cardinal","shaggy","froggy","qwer","kawasaki","kodiak","phpbb","54321","chopper","hooker","whynot","lesbian","snake","teen","ncc1701d","qqqqqq","airplane","britney","avalon","sugar","sublime","wildcat","raven","scarface","elizabet","123654","trucks","wolfpack","pervert","redhead","american","bambam","woody","shaved","snowman","tiger1","chicks","raptor","1969","stingray","shooter","france","stars","madmax","sports","789456","simpsons","lights","chronic","hahaha","packard","hendrix","service","spring","srinivas","spike","252525","bigmac","suck","single","popeye","tattoo","texas","bullet","taurus","sailor","wolves","panthers","japan","strike","pussycat","chris1","loverboy","berlin","sticky","tarheels","russia","wolfgang","testtest","mature","catch22","juice","michael1","nigger","159753","alpha1","trooper","hawkeye","freaky","dodgers","pakistan","machine","pyramid","vegeta","katana","moose","tinker","coyote","infinity","pepsi","letmein1","bang","hercules","james1","tickle","outlaw","browns","billybob","pickle","test1","sucks","pavilion","changeme","caesar","prelude","darkside","bowling","wutang","sunset","alabama","danger","zeppelin","pppppp","2001","ping","darkstar","madonna","qwe123","bigone","casino","charlie1","mmmmmm","integra","wrangler","apache","tweety","qwerty12","bobafett","transam","2323","seattle","ssssss","openup","pandora","pussys","trucker","indigo","storm","malibu","weed","review","babydoll","doggy","dilbert","pegasus","joker","catfish","flipper","fuckit","detroit","cheyenne","bruins","smoke","marino","fetish","xfiles","stinger","pizza","babe","stealth","manutd","gundam","cessna","longhorn","presario","mnbvcxz","wicked","mustang1","victory","21122112","awesome","athena","q1w2e3r4","holiday","knicks","redneck","12341234","gizmo","scully","dragon1","devildog","triumph","bluebird","shotgun","peewee","angel1","metallica","madman","impala","lennon","omega","access14","enterpri","search","smitty","blizzard","unicorn","tight","asdf1234","trigger","truck","beauty","thailand","1234567890","cadillac","castle","bobcat","buddy1","sunny","stones","asian","butt","loveyou","hellfire","hotsex","indiana","panzer","lonewolf","trumpet","colors","blaster","12121212","fireball","precious","jungle","atlanta","gold","corona","polaris","timber","theone","baller","chipper","skyline","dragons","dogs","licker","engineer","kong","pencil","basketba","hornet","barbie","wetpussy","indians","redman","foobar","travel","morpheus","target","141414","hotstuff","photos","rocky1","fuck_inside","dollar","turbo","design","hottie","202020","blondes","4128","lestat","avatar","goforit","random","abgrtyu","jjjjjj","cancer","q1w2e3","smiley","express","virgin","zipper","wrinkle1","babylon","consumer","monkey1","serenity","samurai","99999999","bigboobs","skeeter","joejoe","master1","aaaaa","chocolat","christia","stephani","tang","1234qwer","98765432","sexual","maxima","77777777","buckeye","highland","seminole","reaper","bassman","nugget","lucifer","airforce","nasty","warlock","2121","dodge","chrissy","burger","snatch","pink","gang","maddie","huskers","piglet","photo","dodger","paladin","chubby","buckeyes","hamlet","abcdefgh","bigfoot","sunday","manson","goldfish","garden","deftones","icecream","blondie","spartan","charger","stormy","juventus","galaxy","escort","zxcvb","planet","blues","david1","ncc1701e","1966","51505150","cavalier","gambit","ripper","oicu812","nylons","aardvark","whiskey","bing","plastic","anal","babylon5","loser","racecar","insane","yankees1","mememe","hansolo","chiefs","fredfred","freak","frog","salmon","concrete","zxcv","shamrock","atlantis","wordpass","rommel","1010","predator","massive","cats","sammy1","mister","stud","marathon","rubber","ding","trunks","desire","montreal","justme","faster","irish","1999","jessica1","alpine","diamonds","00000","swinger","shan","stallion","pitbull","letmein2","ming","shadow1","clitoris","fuckers","jackoff","bluesky","sundance","renegade","hollywoo","151515","wolfman","soldier","ling","goddess","manager","sweety","titans","fang","ficken","niners","bubble","hello123","ibanez","sweetpea","stocking","323232","tornado","content","aragorn","trojan","christop","rockstar","geronimo","pascal","crimson","google","fatcat","lovelove","cunts","stimpy","finger","wheels","viper1","latin","greenday","987654321","creampie","hiphop","snapper","funtime","duck","trombone","adult","cookies","mulder","westham","latino","jeep","ravens","drizzt","madness","energy","kinky","314159","slick","rocker","55555555","mongoose","speed","dddddd","catdog","cheng","ghost","gogogo","tottenha","curious","butterfl","mission","january","shark","techno","lancer","lalala","chichi","orion","trixie","delta","bobbob","bomber","kang","1968","spunky","liquid","beagle","granny","network","kkkkkk","1973","biggie","beetle","teacher","toronto","anakin","genius","cocks","dang","karate","snakes","bangkok","fuckyou2","pacific","daytona","infantry","skywalke","sailing","raistlin","vanhalen","huang","blackie","tarzan","strider","sherlock","gong","dietcoke","ultimate","shai","sprite","ting","artist","chai","chao","devil","python","ninja","ytrewq","superfly","456789","tian","jing","jesus1","freedom1","drpepper","chou","hobbit","shen","nolimit","mylove","biscuit","yahoo","shasta","sex4me","smoker","pebbles","pics","philly","tong","tintin","lesbians","cactus","frank1","tttttt","chun","danni","emerald","showme","pirates","lian","dogg","xiao","xian","tazman","tanker","toshiba","gotcha","rang","keng","jazz","bigguy","yuan","tomtom","chaos","fossil","racerx","creamy","bobo","musicman","warcraft","blade","shuang","shun","lick","jian","microsoft","rong","feng","getsome","quality","1977","beng","wwwwww","yoyoyo","zhang","seng","harder","qazxsw","qian","cong","chuan","deng","nang","boeing","keeper","western","1963","subaru","sheng","thuglife","teng","jiong","miao","mang","maniac","pussie","a1b2c3","zhou","zhuang","xing","stonecol","spyder","liang","jiang","memphis","ceng","magic1","logitech","chuang","sesame","shao","poison","titty","kuan","kuai","mian","guan","hamster","guai","ferret","geng","duan","pang","maiden","quan","velvet","nong","neng","nookie","buttons","bian","bingo","biao","zhong","zeng","zhun","ying","zong","xuan","zang","0.0.000","suan","shei","shui","sharks","shang","shua","peng","pian","piao","liao","meng","miami","reng","guang","cang","ruan","diao","luan","qing","chui","chuo","cuan","nuan","ning","heng","huan","kansas","muscle","weng","1passwor","bluemoon","zhui","zhua","xiang","zheng","zhen","zhei","zhao","zhan","yomama","zhai","zhuo","zuan","tarheel","shou","shuo","tiao","leng","kuang","jiao","13579","basket","qiao","qiong","qiang","chuai","nian","niao","niang","huai","22222222","zhuan","zhuai","shuan","shuai","stardust","jumper","66666666","charlott","qwertz","bones","waterloo","2002","11223344","oldman","trains","vertigo","246810","black1","swallow","smiles","standard","alexandr","parrot","user","1976","surfing","pioneer","apple1","asdasd","auburn","hannibal","frontier","panama","welcome1","vette","blue22","shemale","111222","baggins","groovy","global","181818","1979","blades","spanking","byteme","lobster","dawg","japanese","1970","1964","2424","polo","coco","deedee","mikey","1972","171717","1701","strip","jersey","green1","capital","putter","vader","seven7","banshee","grendel","dicks","hidden","iloveu","1980","ledzep","147258","female","bugger","buffett","molson","2020","wookie","sprint","jericho","102030","ranger1","trebor","deepthroat","bonehead","molly1","mirage","models","1984","2468","showtime","squirrel","pentium","anime","gator","powder","twister","connect","neptune","engine","eatshit","mustangs","woody1","shogun","septembe","pooh","jimbo","russian","sabine","voyeur","2525","363636","camel","germany","giant","qqqq","nudist","bone","sleepy","tequila","fighter","obiwan","makaveli","vacation","walnut","1974","ladybug","cantona","ccbill","satan","rusty1","passwor1","columbia","kissme","motorola","william1","1967","zzzz","skater","smut","matthew1","valley","coolio","dagger","boner","bull","horndog","jason1","penguins","rescue","griffey","8j4ye3uz","californ","champs","qwertyuiop","portland","colt45","xxxxxxx","xanadu","tacoma","carpet","gggggg","safety","palace","italia","picturs","picasso","thongs","tempest","asd123","hairy","foxtrot","nimrod","hotboy","343434","1111111","asdfghjkl","goose","overlord","stranger","454545","shaolin","sooners","socrates","spiderman","peanuts","13131313","andrew1","filthy","ohyeah","africa","intrepid","pickles","assass","fright","potato","hhhhhh","kingdom","weezer","424242","pepsi1","throat","looker","puppy","butch","sweets","megadeth","analsex","nymets","ddddddd","bigballs","oakland","oooooo","qweasd","chucky","carrot","chargers","discover","dookie","condor","horny1","sunrise","sinner","jojo","megapass","martini","assfuck","ffffff","mushroom","jamaica","7654321","77777","cccccc","gizmodo","tractor","mypass","hongkong","1975","blue123","pissing","thomas1","redred","basketball","satan666","dublin","bollox","kingkong","1971","22222","272727","sexx","bbbb","grizzly","passat","defiant","bowler","knickers","monitor","wisdom","slappy","thor","letsgo","robert1","brownie","098765","playtime","lightnin","atomic","goku","llllll","qwaszx","cosmos","bosco","knights","beast","slapshot","assword","frosty","dumbass","mallard","dddd","159357","titleist","aussie","golfing","doobie","loveit","werewolf","vipers","1965","blabla","surf","sucking","tardis","thegame","legion","rebels","sarah1","onelove","loulou","toto","blackcat","0007","tacobell","soccer1","jedi","method","poopie","boob","breast","kittycat","belly","pikachu","thunder1","thankyou","celtics","frogger","scoobydo","sabbath","coltrane","budman","jackal","zzzzz","licking","gopher","geheim","lonestar","primus","pooper","newpass","brasil","heather1","husker","element","moomoo","beefcake","zzzzzzzz","shitty","smokin","jjjj","anthony1","anubis","backup","gorilla","fuckface","lowrider","punkrock","traffic","delta1","amazon","fatass","dodgeram","dingdong","qqqqqqqq","breasts","boots","honda1","spidey","poker","temp","johnjohn","147852","asshole1","dogdog","tricky","crusader","syracuse","spankme","speaker","meridian","amadeus","harley1","falcons","turkey50","kenwood","keyboard","ilovesex","1978","shazam","shalom","lickit","jimbob","roller","fatman","sandiego","magnus","cooldude","clover","mobile","plumber","texas1","tool","topper","mariners","rebel","caliente","celica","oxford","osiris","orgasm","punkin","porsche9","tuesday","breeze","bossman","kangaroo","latinas","astros","scruffy","qwertyu","hearts","jammer","java","1122","goodtime","chelsea1","freckles","flyboy","doodle","nebraska","bootie","kicker","webmaster","vulcan","191919","blueeyes","321321","farside","rugby","director","pussy69","power1","hershey","hermes","monopoly","birdman","blessed","blackjac","southern","peterpan","thumbs","fuckyou1","rrrrrr","a1b2c3d4","coke","bohica","elvis1","blacky","sentinel","snake1","richard1","1234abcd","guardian","candyman","fisting","scarlet","dildo","pancho","mandingo","lucky7","condom","munchkin","billyboy","summer1","sword","skiing","site","sony","thong","rootbeer","assassin","fffff","fitness","durango","postal","achilles","kisses","warriors","plymouth","topdog","asterix","hallo","cameltoe","fuckfuck","eeeeee","sithlord","theking","avenger","backdoor","chevrole","trance","cosworth","houses","homers","eternity","kingpin","verbatim","incubus","1961","blond","zaphod","shiloh","spurs","mighty","aliens","charly","dogman","omega1","printer","aggies","deadhead","bitch1","stone55","pineappl","thekid","rockets","camels","formula","oracle","pussey","porkchop","abcde","clancy","mystic","inferno","blackdog","steve1","alfa","grumpy","flames","puffy","proxy","valhalla","unreal","herbie","engage","yyyyyy","010101","pistol","celeb","gggg","portugal","a12345","newbie","mmmm","1qazxsw2","zorro","writer","stripper","sebastia","spread","links","metal","1221","565656","funfun","trojans","cyber","hurrican","moneys","1x2zkg8w","zeus","tomato","lion","atlantic","usa123","trans","aaaaaaa","homerun","hyperion","kevin1","blacks","44444444","skittles","fart","gangbang","fubar","sailboat","oilers","buster1","hithere","immortal","sticks","pilot","lexmark","jerkoff","maryland","cheers","possum","cutter","muppet","swordfish","sport","sonic","peter1","jethro","rockon","asdfghj","pass123","pornos","ncc1701a","bootys","buttman","bonjour","1960","bears","362436","spartans","tinman","threesom","maxmax","1414","bbbbb","camelot","chewie","gogo","fusion","saint","dilligaf","nopass","hustler","hunter1","whitey","beast1","yesyes","spank","smudge","pinkfloy","patriot","lespaul","hammers","formula1","sausage","scooter1","orioles","oscar1","colombia","cramps","exotic","iguana","suckers","slave","topcat","lancelot","magelan","racer","crunch","british","steph","456123","skinny","seeking","rockhard","filter","freaks","sakura","pacman","poontang","newlife","homer1","klingon","watcher","walleye","tasty","sinatra","starship","steel","starbuck","poncho","amber1","gonzo","catherin","candle","firefly","goblin","scotch","diver","usmc","huskies","kentucky","kitkat","beckham","bicycle","yourmom","studio","33333333","splash","jimmy1","12344321","sapphire","mailman","raiders1","ddddd","excalibu","illini","imperial","lansing","maxx","gothic","golfball","facial","front242","macdaddy","qwer1234","vectra","cowboys1","crazy1","dannyboy","aquarius","franky","ffff","sassy","pppp","pppppppp","prodigy","noodle","eatpussy","vortex","wanking","billy1","siemens","phillies","groups","chevy1","cccc","gggggggg","doughboy","dracula","nurses","loco","lollipop","utopia","chrono","cooler","nevada","wibble","summit","1225","capone","fugazi","panda","qazwsxed","puppies","triton","9876","nnnnnn","momoney","iforgot","wolfie","studly","hamburg","81fukkc","741852","catman","china","gagging","scott1","oregon","qweqwe","crazybab","daniel1","cutlass","holes","mothers","music1","walrus","1957","bigtime","xtreme","simba","ssss","rookie","bathing","rotten","maestro","turbo1","99999","butthole","hhhh","yoda","shania","phish","thecat","rightnow","baddog","greatone","gateway1","abstr","napster","brian1","bogart","hitler","wildfire","jackson1","1981","beaner","yoyo","0.0.0.000","super1","select","snuggles","slutty","phoenix1","technics","toon","raven1","rayray","123789","1066","albion","greens","gesperrt","brucelee","hehehe","kelly1","mojo","1998","bikini","woofwoof","yyyy","strap","sites","central","f**k","nyjets","punisher","username","vanilla","twisted","bunghole","viagra","veritas","pony","titts","labtec","jenny1","masterbate","mayhem","redbull","govols","gremlin","505050","gmoney","rovers","diamond1","trident","abnormal","deskjet","cuddles","bristol","milano","vh5150","jarhead","1982","bigbird","bizkit","sixers","slider","star69","starfish","penetration","tommy1","john316","caligula","flicks","films","railroad","cosmo","cthulhu","br0d3r","bearbear","swedish","spawn","patrick1","reds","anarchy","groove","fuckher","oooo","airbus","cobra1","clips","delete","duster","kitty1","mouse1","monkeys","jazzman","1919","262626","swinging","stroke","stocks","sting","pippen","labrador","jordan1","justdoit","meatball","females","vector","cooter","defender","nike","bubbas","bonkers","kahuna","wildman","4121","sirius","static","piercing","terror","teenage","leelee","microsof","mechanic","robotech","rated","chaser","salsero","macross","quantum","tsunami","daddy1","cruise","newpass6","nudes","hellyeah","1959","zaq12wsx","striker","spice","spectrum","smegma","thumb","jjjjjjjj","mellow","cancun","cartoon","sabres","samiam","oranges","oklahoma","lust","denali","nude","noodles","brest","hooter","mmmmmmmm","warthog","blueblue","zappa","wolverine","sniffing","jjjjj","calico","freee","rover","pooter","closeup","bonsai","emily1","keystone","iiii","1955","yzerman","theboss","tolkien","megaman","rasta","bbbbbbbb","hal9000","goofy","gringo","gofish","gizmo1","samsam","scuba","onlyme","tttttttt","corrado","clown","clapton","bulls","jayhawk","wwww","sharky","seeker","ssssssss","pillow","thesims","lighter","lkjhgf","melissa1","marcius2","guiness","gymnast","casey1","goalie","godsmack","lolo","rangers1","poppy","clemson","clipper","deeznuts","holly1","eeee","kingston","yosemite","sucked","sex123","sexy69","pic's","tommyboy","masterbating","gretzky","happyday","frisco","orchid","orange1","manchest","aberdeen","ne1469","boxing","korn","intercourse","161616","1985","ziggy","supersta","stoney","amature","babyboy","bcfields","goliath","hack","hardrock","frodo","scout","scrappy","qazqaz","tracker","active","craving","commando","cohiba","cyclone","bubba69","katie1","mpegs","vsegda","irish1","sexy1","smelly","squerting","lions","jokers","jojojo","meathead","ashley1","groucho","cheetah","champ","firefox","gandalf1","packer","love69","tyler1","typhoon","tundra","bobby1","kenworth","village","volley","wolf359","0420","000007","swimmer","skydive","smokes","peugeot","pompey","legolas","redhot","rodman","redalert","grapes","4runner","carrera","floppy","ou8122","quattro","cloud9","davids","nofear","busty","homemade","mmmmm","whisper","vermont","webmaste","wives","insertion","jayjay","philips","topher","temptress","midget","ripken","havefun","canon","celebrity","ghetto","ragnarok","usnavy","conover","cruiser","dalshe","nicole1","buzzard","hottest","kingfish","misfit","milfnew","warlord","wassup","bigsexy","blackhaw","zippy","tights","kungfu","labia","meatloaf","area51","batman1","bananas","636363","ggggg","paradox","queens","adults","aikido","cigars","hoosier","eeyore","moose1","warez","interacial","streaming","313131","pertinant","pool6123","mayday","animated","banker","baddest","gordon24","ccccc","fantasies","aisan","deadman","homepage","ejaculation","whocares","iscool","jamesbon","1956","1pussy","womam","sweden","skidoo","spock","sssss","pepper1","pinhead","micron","allsop","amsterda","gunnar","666999","february","fletch","george1","sapper","sasha1","luckydog","lover1","magick","popopo","ultima","cypress","businessbabe","brandon1","vulva","vvvv","jabroni","bigbear","yummy","010203","searay","secret1","sinbad","sexxxx","soleil","software","piccolo","thirteen","leopard","legacy","memorex","redwing","rasputin","134679","anfield","greenbay","catcat","feather","scanner","pa55word","contortionist","danzig","daisy1","hores","exodus","iiiiii","1001","subway","snapple","sneakers","sonyfuck","picks","poodle","test1234","llll","junebug","marker","mellon","ronaldo","roadkill","amanda1","asdfjkl","beaches","great1","cheerleaers","doitnow","ozzy","boxster","brighton","housewifes","kkkk","mnbvcx","moocow","vides","1717","bigmoney","blonds","1000","storys","stereo","4545","420247","seductive","sexygirl","lesbean","justin1","124578","cabbage","canadian","gangbanged","dodge1","dimas","malaka","puss","probes","coolman","nacked","hotpussy","erotica","kool","implants","intruder","bigass","zenith","woohoo","womans","tango","pisces","laguna","maxell","andyod22","barcelon","chainsaw","chickens","flash1","orgasms","magicman","profit","pusyy","pothead","coconut","chuckie","clevelan","builder","budweise","hotshot","horizon","experienced","mondeo","wifes","1962","stumpy","smiths","slacker","pitchers","passwords","laptop","allmine","alliance","bbbbbbb","asscock","halflife","88888","chacha","saratoga","sandy1","doogie","qwert40","transexual","close-up","ib6ub9","volvo","jacob1","iiiii","beastie","sunnyday","stoned","sonics","starfire","snapon","pictuers","pepe","testing1","tiberius","lisalisa","lesbain","litle","retard","ripple","austin1","badgirl","golfgolf","flounder","royals","dragoon","dickie","passwor","majestic","poppop","trailers","nokia","bobobo","br549","minime","mikemike","whitesox","1954","3232","353535","seamus","solo","sluttey","pictere","titten","lback","1024","goodluck","fingerig","gallaries","goat","passme","oasis","lockerroom","logan1","rainman","treasure","custom","cyclops","nipper","bucket","homepage-","hhhhh","momsuck","indain","2345","beerbeer","bimmer","stunner","456456","tootsie","testerer","reefer","1012","harcore","gollum","545454","chico","caveman","fordf150","fishes","gaymen","saleen","doodoo","pa55w0rd","presto","qqqqq","cigar","bogey","helloo","dutch","kamikaze","wasser","vietnam","visa","japanees","0123","swords","slapper","peach","masterbaiting","redwood","1005","ametuer","chiks","fucing","sadie1","panasoni","mamas","rambo","unknown","absolut","dallas1","housewife","keywest","kipper","18436572","1515","zxczxc","303030","shaman","terrapin","masturbation","mick","redfish","1492","angus","goirish","hardcock","forfun","galary","freeporn","duchess","olivier","lotus","pornographic","ramses","purdue","traveler","crave","brando","enter1","killme","moneyman","welder","windsor","wifey","indon","yyyyy","taylor1","4417","picher","pickup","thumbnils","johnboy","jets","ameteur","amateurs","apollo13","hambone","goldwing","5050","sally1","doghouse","padres","pounding","quest","truelove","underdog","trader","climber","bolitas","hohoho","beanie","beretta","wrestlin","stroker","sexyman","jewels","johannes","mets","rhino","bdsm","balloons","grils","happy123","flamingo","route66","devo","outkast","paintbal","magpie","llllllll","twilight","critter","cupcake","nickel","bullseye","knickerless","videoes","binladen","xerxes","slim","slinky","pinky","thanatos","meister","menace","retired","albatros","balloon","goten","5551212","getsdown","donuts","nwo4life","tttt","comet","deer","dddddddd","deeznutz","nasty1","nonono","enterprise","eeeee","misfit99","milkman","vvvvvv","1818","blueboy","bigbutt","tech","toolman","juggalo","jetski","barefoot","50spanks","gobears","scandinavian","cubbies","nitram","kings","bilbo","yumyum","zzzzzzz","stylus","321654","shannon1","server","squash","starman","steeler","phrases","techniques","laser","135790","athens","cbr600","chemical","fester","gangsta","fucku2","droopy","objects","passwd","lllll","manchester","vedder","clit","chunky","darkman","buckshot","buddah","boobed","henti","winter1","bigmike","beta","zidane","talon","slave1","pissoff","thegreat","lexus","matador","readers","armani","goldstar","5656","fmale","fuking","fucku","ggggggg","sauron","diggler","pacers","looser","pounded","premier","triangle","cosmic","depeche","norway","helmet","mustard","misty1","jagger","3x7pxr","silver1","snowboar","penetrating","photoes","lesbens","lindros","roadking","rockford","1357","143143","asasas","goodboy","898989","chicago1","ferrari1","galeries","godfathe","gawker","gargoyle","gangster","rubble","rrrr","onetime","pussyman","pooppoop","trapper","cinder","newcastl","boricua","bunny1","boxer","hotred","hockey1","edward1","moscow","mortgage","bigtit","snoopdog","joshua1","july","1230","assholes","frisky","sanity","divine","dharma","lucky13","akira","butterfly","hotbox","hootie","howdy","earthlink","kiteboy","westwood","1988","blackbir","biggles","wrench","wrestle","slippery","pheonix","penny1","pianoman","thedude","jenn","jonjon","jones1","roadrunn","arrow","azzer","seahawks","diehard","dotcom","tunafish","chivas","cinnamon","clouds","deluxe","northern","boobie","momomo","modles","volume","23232323","bluedog","wwwwwww","zerocool","yousuck","pluto","limewire","joung","awnyce","gonavy","haha","films+pic+galeries","girsl","fuckthis","girfriend","uncencored","a123456","chrisbln","combat","cygnus","cupoi","netscape","hhhhhhhh","eagles1","elite","knockers","1958","tazmania","shonuf","pharmacy","thedog","midway","arsenal1","anaconda","australi","gromit","gotohell","787878","66666","carmex2","camber","gator1","ginger1","fuzzy","seadoo","lovesex","rancid","uuuuuu","911911","bulldog1","heater","monalisa","mmmmmmm","whiteout","virtual","jamie1","japanes","james007","2727","2469","blam","bitchass","zephyr","stiffy","sweet1","southpar","spectre","tigger1","tekken","lakota","lionking","jjjjjjj","megatron","1369","hawaiian","gymnastic","golfer1","gunners","7779311","515151","sanfran","optimus","panther1","love1","maggie1","pudding","aaron1","delphi","niceass","bounce","house1","killer1","momo","musashi","jammin","2003","234567","wp2003wp","submit","sssssss","spikes","sleeper","passwort","kume","meme","medusa","mantis","reebok","1017","artemis","harry1","cafc91","fettish","oceans","oooooooo","mango","ppppp","trainer","uuuu","909090","death1","bullfrog","hokies","holyshit","eeeeeee","jasmine1","&","&","spinner","jockey","babyblue","gooner","474747","cheeks","pass1234","parola","okokok","poseidon","989898","crusher","cubswin","nnnn","kotaku","mittens","whatsup","vvvvv","iomega","insertions","bengals","biit","yellow1","012345","spike1","sowhat","pitures","pecker","theend","hayabusa","hawkeyes","florian","qaz123","usarmy","twinkle","chuckles","hounddog","hover","hothot","europa","kenshin","kojak","mikey1","water1","196969","wraith","zebra","wwwww","33333","simon1","spider1","snuffy","philippe","thunderb","teddy1","marino13","maria1","redline","renault","aloha","handyman","cerberus","gamecock","gobucks","freesex","duffman","ooooo","nuggets","magician","longbow","preacher","porno1","chrysler","contains","dalejr","navy","buffy1","hedgehog","hoosiers","honey1","hott","heyhey","dutchess","everest","wareagle","ihateyou","sunflowe","3434","senators","shag","spoon","sonoma","stalker","poochie","terminal","terefon","maradona","1007","142536","alibaba","america1","bartman","astro","goth","chicken1","cheater","ghost1","passpass","oral","r2d2c3po","civic","cicero","myxworld","kkkkk","missouri","wishbone","infiniti","1a2b3c","1qwerty","wonderboy","shojou","sparky1","smeghead","poiuy","titanium","lantern","jelly","1213","bayern","basset","gsxr750","cattle","fishing1","fullmoon","gilles","dima","obelix","popo","prissy","ramrod","bummer","hotone","dynasty","entry","konyor","missy1","282828","xyz123","426hemi","404040","seinfeld","pingpong","lazarus","marine1","12345a","beamer","babyface","greece","gustav","7007","ccccccc","faggot","foxy","gladiato","duckie","dogfood","packers1","longjohn","radical","tuna","clarinet","danny1","novell","bonbon","kashmir","kiki","mortimer","modelsne","moondog","vladimir","insert","1953","zxc123","supreme","3131","sexxx","softail","poipoi","pong","mars","martin1","rogue","avalanch","audia4","55bgates","cccccccc","came11","figaro","dogboy","dnsadm","dipshit","paradigm","othello","operator","tripod","chopin","coucou","cocksuck","borussia","heritage","hiziad","homerj","mullet","whisky","4242","speedo","starcraf","skylar","spaceman","piggy","tiger2","legos","jezebel","joker1","mazda","727272","chester1","rrrrrrrr","dundee","lumber","ppppppp","tranny","aaliyah","admiral","comics","delight","buttfuck","homeboy","eternal","kilroy","violin","wingman","walmart","bigblue","blaze","beemer","beowulf","bigfish","yyyyyyy","woodie","yeahbaby","0123456","tbone","syzygy","starter","linda1","merlot","mexican","11235813","banner","bangbang","badman","barfly","grease","charles1","ffffffff","doberman","dogshit","overkill","coolguy","claymore","demo","nomore","hhhhhhh","hondas","iamgod","enterme","electron","eastside","minimoni","mybaby","wildbill","wildcard","ipswich","200000","bearcat","zigzag","yyyyyyyy","sweetnes","369369","skyler","skywalker","pigeon","tipper","asdf123","alphabet","asdzxc","babybaby","banane","guyver","graphics","chinook","florida1","flexible","fuckinside","ursitesux","tototo","adam12","christma","chrome","buddie","bombers","hippie","misfits","292929","woofer","wwwwwwww","stubby","sheep","sparta","stang","spud","sporty","pinball","just4fun","maxxxx","rebecca1","fffffff","freeway","garion","rrrrr","sancho","outback","maggot","puddin","987456","hoops","mydick","19691969","bigcat","shiner","silverad","templar","lamer","juicy","mike1","maximum","1223","10101010","arrows","alucard","haggis","cheech","safari","dog123","orion1","paloma","qwerasdf","presiden","vegitto","969696","adonis","cookie1","newyork1","buddyboy","hellos","heineken","eraser","moritz","millwall","visual","jaybird","1983","beautifu","zodiac","steven1","sinister","slammer","smashing","slick1","sponge","teddybea","ticklish","jonny","1211","aptiva","applepie","bailey1","guitar1","canyon","gagged","fuckme1","digital1","dinosaur","98765","90210","clowns","cubs","deejay","nigga","naruto","boxcar","icehouse","hotties","electra","widget","1986","2004","bluefish","bingo1","*****","stratus","sultan","storm1","44444","4200","sentnece","sexyboy","sigma","smokie","spam","pippo","temppass","manman","1022","bacchus","aztnm","axio","bamboo","hakr","gregor","hahahaha","5678","camero1","dolphin1","paddle","magnet","qwert1","pyon","porsche1","tripper","noway","burrito","bozo","highheel","hookem","eddie1","entropy","kkkkkkkk","kkkkkkk","illinois","1945","1951","24680","21212121","100000","stonecold","taco","subzero","sexxxy","skolko","skyhawk","spurs1","sputnik","testpass","jiggaman","1224","hannah1","525252","4ever","carbon","scorpio1","rt6ytere","madison1","loki","coolness","coldbeer","citadel","monarch","morgan1","washingt","1997","bella1","yaya","superb","taxman","studman","3636","pizzas","tiffany1","lassie","larry1","joseph1","mephisto","reptile","razor","1013","hammer1","gypsy","grande","camper","chippy","cat123","chimera","fiesta","glock","domain","dieter","dragonba","onetwo","nygiants","password2","quartz","prowler","prophet","towers","ultra","cocker","corleone","dakota1","cumm","nnnnnnn","boxers","heynow","iceberg","kittykat","wasabi","vikings1","beerman","splinter","snoopy1","pipeline","mickey1","mermaid","micro","meowmeow","redbird","baura","chevys","caravan","frogman","diving","dogger","draven","drifter","oatmeal","paris1","longdong","quant4307s","rachel1","vegitta","cobras","corsair","dadada","mylife","bowwow","hotrats","eastwood","moonligh","modena","illusion","iiiiiii","jayhawks","swingers","shocker","shrimp","sexgod","squall","poiu","tigers1","toejam","tickler","julie1","jimbo1","jefferso","michael2","rodeo","robot","1023","annie1","bball","happy2","charter","flasher","falcon1","fiction","fastball","gadget","scrabble","diaper","dirtbike","oliver1","paco","macman","poopy","popper","postman","ttttttt","acura","cowboy1","conan","daewoo","nemrac58","nnnnn","nextel","bobdylan","eureka","kimmie","kcj9wx5n","killbill","musica","volkswag","wage","windmill","wert","vintage","iloveyou1","itsme","zippo","311311","starligh","smokey1","snappy","soulmate","plasma","krusty","just4me","marius","rebel1","1123","audi","fick","goaway","rusty2","dogbone","doofus","ooooooo","oblivion","mankind","mahler","lllllll","pumper","puck","pulsar","valkyrie","tupac","compass","concorde","cougars","delaware","niceguy","nocturne","bob123","boating","bronze","herewego","hewlett","houhou","earnhard","eeeeeeee","mingus","mobydick","venture","verizon","imation","1950","1948","1949","223344","bigbig","wowwow","sissy","spiker","snooker","sluggo","player1","jsbach","jumbo","medic","reddevil","reckless","123456a","1125","1031","astra","gumby","757575","585858","chillin","fuck1","radiohea","upyours","trek","coolcool","classics","choochoo","nikki1","nitro","boytoy","excite","kirsty","wingnut","wireless","icu812","1master","beatle","bigblock","wolfen","summer99","sugar1","tartar","sexysexy","senna","sexman","soprano","platypus","pixies","telephon","laura1","laurent","rimmer","1020","12qwaszx","hamish","halifax","fishhead","forum","dododo","doit","paramedi","lonesome","mandy1","uuuuu","uranus","ttttt","bruce1","helper","hopeful","eduard","dusty1","kathy1","moonbeam","muscles","monster1","monkeybo","windsurf","vvvvvvv","vivid","install","1947","187187","1941","1952","susan1","31415926","sinned","sexxy","smoothie","snowflak","playstat","playa","playboy1","toaster","jerry1","marie1","mason1","merlin1","roger1","roadster","112358","1121","andrea1","bacardi","hardware","789789","5555555","captain1","fergus","sascha","rrrrrrr","dome","onion","lololo","qqqqqqq","undertak","uuuuuuuu","uuuuuuu","cobain","cindy1","coors","descent","nimbus","nomad","nanook","norwich","bombay","broker","hookup","kiwi","winners","jackpot","1a2b3c4d","1776","beardog","bighead","bird33","0987","spooge","pelican","peepee","titan","thedoors","jeremy1","altima","baba","hardone","5454","catwoman","finance","farmboy","farscape","genesis1","salomon","loser1","r2d2","pumpkins","chriss","cumcum","ninjas","ninja1","killers","miller1","islander","jamesbond","intel","19841984","2626","bizzare","blue12","biker","yoyoma","sushi","shitface","spanker","steffi","sphinx","please1","paulie","pistons","tiburon","maxwell1","mdogg","rockies","armstron","alejandr","arctic","banger","audio","asimov","753951","4you","chilly","care1839","flyfish","fantasia","freefall","sandrine","oreo","ohshit","macbeth","madcat","loveya","qwerqwer","colnago","chocha","cobalt","crystal1","dabears","nevets","nineinch","broncos1","epsilon","kestrel","winston1","warrior1","iiiiiiii","iloveyou2","1616","woowoo","sloppy","specialk","tinkerbe","jellybea","reader","redsox1","1215","1112","arcadia","baggio","555666","cayman","cbr900rr","gabriell","glennwei","sausages","disco","pass1","lovebug","macmac","puffin","vanguard","trinitro","airwolf","aaa111","cocaine","cisco","datsun","bricks","bumper","eldorado","kidrock","wizard1","whiskers","wildwood","istheman","25802580","bigones","woodland","wolfpac","strawber","3030","sheba1","sixpack","peace1","physics","tigger2","toad","megan1","meow","ringo","amsterdam","717171","686868","5424","canuck","football1","footjob","fulham","seagull","orgy","lobo","mancity","vancouve","vauxhall","acidburn","derf","myspace1","boozer","buttercu","hola","minemine","munch","1dragon","biology","bestbuy","bigpoppa","blackout","blowfish","bmw325","bigbob","stream","talisman","tazz","sundevil","3333333","skate","shutup","shanghai","spencer1","slowhand","pinky1","tootie","thecrow","jubilee","jingle","matrix1","manowar","messiah","resident","redbaron","romans","andromed","athlon","beach1","badgers","guitars","harald","harddick","gotribe","6996","7grout","5wr2i7h8","635241","chase1","fallout","fiddle","fenris","francesc","fortuna","fairlane","felix1","gasman","fucks","sahara","sassy1","dogpound","dogbert","divx1","manila","pornporn","quasar","venom","987987","access1","clippers","daman","crusty","nathan1","nnnnnnnn","bruno1","budapest","kittens","kerouac","mother1","waldo1","whistler","whatwhat","wanderer","idontkno","1942","1946","bigdawg","bigpimp","zaqwsx","414141","3000gt","434343","serpent","smurf","pasword","thisisit","john1","robotics","redeye","rebelz","1011","alatam","asians","bama","banzai","harvest","575757","5329","fatty","fender1","flower2","funky","sambo","drummer1","dogcat","oedipus","osama","prozac","private1","rampage","concord","cinema","cornwall","cleaner","ciccio","clutch","corvet07","daemon","bruiser","boiler","hjkl","egghead","mordor","jamess","iverson3","bluesman","zouzou","090909","1002","stone1","4040","sexo","smith1","sperma","sneaky","polska","thewho","terminat","krypton","lekker","johnson1","johann","rockie","aspire","goodie","cheese1","fenway","fishon","fishin","fuckoff1","girls1","doomsday","pornking","ramones","rabbits","transit","aaaaa1","boyz","bookworm","bongo","bunnies","buceta","highbury","henry1","eastern","mischief","mopar","ministry","vienna","wildone","bigbooty","beavis1","xxxxxx1","yogibear","000001","0815","zulu","420000","sigmar","sprout","stalin","lkjhgfds","lagnaf","rolex","redfox","referee","123123123","1231","angus1","ballin","attila","greedy","grunt","747474","carpedie","caramel","foxylady","gatorade","futbol","frosch","saiyan","drums","donner","doggy1","drum","doudou","nutmeg","quebec","valdepen","tosser","tuscl","comein","cola","deadpool","bremen","hotass","hotmail1","eskimo","eggman","koko","kieran","katrin","kordell1","komodo","mone","munich","vvvvvvvv","jackson5","2222222","bergkamp","bigben","zanzibar","xxx123","sunny1","373737","slayer1","snoop","peachy","thecure","little1","jennaj","rasta69","1114","aries","havana","gratis","calgary","checkers","flanker","salope","dirty1","draco","dogface","luv2epus","rainbow6","qwerty123","umpire","turnip","vbnm","tucson","troll","codered","commande","neon","nico","nightwin","boomer1","bushido","hotmail0","enternow","keepout","karen1","mnbv","viewsoni","volcom","wizards","1995","berkeley","woodstoc","tarpon","shinobi","starstar","phat","toolbox","julien","johnny1","joebob","riders","reflex","120676","1235","angelus","anthrax","atlas","grandam","harlem","hawaii50","655321","cabron","challeng","callisto","firewall","firefire","flyer","flower1","gambler","frodo1","sam123","scania","dingo","papito","passmast","ou8123","randy1","twiggy","travis1","treetop","addict","admin1","963852","aceace","cirrus","bobdole","bonjovi","bootsy","boater","elway7","kenny1","moonshin","montag","wayne1","white1","jazzy","jakejake","1994","1991","2828","bluejays","belmont","sensei","southpark","peeper","pharao","pigpen","tomahawk","teensex","leedsutd","jeepster","jimjim","josephin","melons","matthias","robocop","1003","1027","antelope","azsxdc","gordo","hazard","granada","8989","7894","ceasar","cabernet","cheshire","chelle","candy1","fergie","fidelio","giorgio","fuckhead","dominion","qawsed","trucking","chloe1","daddyo","nostromo","boyboy","booster","bucky","honolulu","esquire","dynamite","mollydog","windows1","waffle","wealth","vincent1","jabber","jaguars","javelin","irishman","idefix","bigdog1","blue42","blanked","blue32","biteme1","bearcats","yessir","sylveste","sunfire","tbird","stryker","3ip76k2","sevens","pilgrim","tenchi","titman","leeds","lithium","linkin","marijuan","mariner","markie","midnite","reddwarf","1129","123asd","12312312","allstar","albany","asdf12","aspen","hardball","goldfing","7734","49ers","carnage","callum","carlos1","fitter","fandango","gofast","gamma","fucmy69","scrapper","dogwood","django","magneto","premium","9999999","abc1234","newyear","bookie","bounty","brown1","bologna","elway","killjoy","klondike","mouser","wayer","impreza","insomnia","24682468","2580","24242424","billbill","bellaco","blues1","blunts","teaser","sf49ers","shovel","solitude","spikey","pimpdadd","timeout","toffee","lefty","johndoe","johndeer","mega","manolo","ratman","robin1","1124","1210","1028","1226","babylove","barbados","gramma","646464","carpente","chaos1","fishbone","fireblad","frogs","screamer","scuba1","ducks","doggies","dicky","obsidian","rams","tottenham","aikman","comanche","corolla","cumslut","cyborg","boston1","houdini","helmut","elvisp","keksa12","monty1","wetter","watford","wiseguy","1989","1987","20202020","biatch","beezer","bigguns","blueball","bitchy","wyoming","yankees2","wrestler","stupid1","sealteam","sidekick","simple1","smackdow","sporting","spiral","smeller","plato","tophat","test2","toomuch","jello","junkie","maxim","maxime","meadow","remingto","roofer","124038","1018","1269","1227","123457","arkansas","aramis","beaker","barcelona","baltimor","googoo","goochi","852456","4711","catcher","champ1","fortress","fishfish","firefigh","geezer","rsalinas","samuel1","saigon","scooby1","dick1","doom","dontknow","magpies","manfred","vader1","universa","tulips","mygirl","bowtie","holycow","honeys","enforcer","waterboy","1992","23skidoo","bimbo","blue11","birddog","zildjian","030303","stinker","stoppedby","sexybabe","speakers","slugger","spotty","smoke1","polopolo","perfect1","torpedo","lakeside","jimmys","junior1","masamune","1214","april1","grinch","767676","5252","cherries","chipmunk","cezer121","carnival","capecod","finder","fearless","goats","funstuff","gideon","savior","seabee","sandro","schalke","salasana","disney1","duckman","pancake","pantera1","malice","love123","qwert123","tracer","creation","cwoui","nascar24","hookers","erection","ericsson","edthom","kokoko","kokomo","mooses","inter","1michael","1993","19781978","25252525","shibby","shamus","skibum","sheepdog","sex69","spliff","slipper","spoons","spanner","snowbird","toriamos","temp123","tennesse","lakers1","jomama","mazdarx7","recon","revolver","1025","1101","barney1","babycake","gotham","gravity","hallowee","616161","515000","caca","cannabis","chilli","fdsa","getout","fuck69","gators1","sable","rumble","dolemite","dork","duffer","dodgers1","onions","logger","lookout","magic32","poon","twat","coventry","citroen","civicsi","cocksucker","coochie","compaq1","nancy1","buzzer","boulder","butkus","bungle","hogtied","hotgirls","heidi1","eggplant","mustang6","monkey12","wapapapa","wendy1","volleyba","vibrate","blink","birthday4","xxxxx1","stephen1","suburban","sheeba","start1","soccer10","starcraft","soccer12","peanut1","plastics","penthous","peterbil","tetsuo","torino","tennis1","termite","lemmein","lakewood","jughead","melrose","megane","redone","angela1","goodgirl","gonzo1","golden1","gotyoass","656565","626262","capricor","chains","calvin1","getmoney","gabber","runaway","salami","dungeon","dudedude","opus","paragon","panhead","pasadena","opendoor","odyssey","magellan","printing","prince1","trustme","nono","buffet","hound","kajak","killkill","moto","winner1","vixen","whiteboy","versace","voyager1","indy","jackjack","bigal","beech","biggun","blake1","blue99","big1","synergy","success1","336699","sixty9","shark1","simba1","sebring","spongebo","spunk","springs","sliver","phialpha","password9","pizza1","pookey","tickling","lexingky","lawman","joe123","mike123","romeo1","redheads","apple123","backbone","aviation","green123","carlitos","byebye","cartman1","camden","chewy","camaross","favorite6","forumwp","ginscoot","fruity","sabrina1","devil666","doughnut","pantie","oldone","paintball","lumina","rainbow1","prosper","umbrella","ajax","951753","achtung","abc12345","compact","corndog","deerhunt","darklord","dank","nimitz","brandy1","hetfield","holein1","hillbill","hugetits","evolutio","kenobi","whiplash","wg8e3wjf","istanbul","invis","1996","bigjohn","bluebell","beater","benji","bluejay","xyzzy","suckdick","taichi","stellar","shaker","semper","splurge","squeak","pearls","playball","pooky","titfuck","joemama","johnny5","marcello","maxi","rhubarb","ratboy","reload","1029","1030","1220","bbking","baritone","gryphon","57chevy","494949","celeron","fishy","gladiator","fucker1","roswell","dougie","dicker","diva","donjuan","nympho","racers","truck1","trample","acer","cricket1","climax","denmark","cuervo","notnow","nittany","neutron","bosco1","buffa","breaker","hello2","hydro","kisskiss","kittys","montecar","modem","mississi","20012001","bigdick1","benfica","yahoo1","striper","tabasco","supra","383838","456654","seneca","shuttle","penguin1","pathfind","testibil","thethe","jeter2","marma","mark1","metoo","republic","rollin","redleg","redbone","redskin","1245","anthony7","altoids","barley","asswipe","bauhaus","bbbbbb1","gohome","harrier","golfpro","goldeney","818181","6666666","5000","5rxypn","cameron1","checker","calibra","freefree","faith1","fdm7ed","giraffe","giggles","fringe","scamper","rrpass1","screwyou","dimples","pacino","ontario","passthie","oberon","quest1","postov1000","puppydog","puffer","qwerty7","tribal","adam25","a1234567","collie","cleopatr","davide","namaste","buffalo1","bonovox","bukkake","burner","bordeaux","burly","hun999","enters","mohawk","vgirl","jayden","1812","1943","222333","bigjim","bigd","zoom","wordup","ziggy1","yahooo","workout","young1","xmas","zzzzzz1","surfer1","strife","sunlight","tasha1","skunk","sprinter","peaches1","pinetree","plum","pimping","theforce","thedon","toocool","laddie","lkjh","jupiter1","matty","redrose","1200","102938","antares","austin31","goose1","737373","78945612","789987","6464","calimero","caster","casper1","cement","chevrolet","chessie","caddy","canucks","fellatio","f00tball","gateway2","gamecube","rugby1","scheisse","dshade","dixie1","offshore","lucas1","macaroni","manga","pringles","puff","trouble1","ussy","coolhand","colonial","colt","darthvad","cygnusx1","natalie1","newark","hiking","errors","elcamino","koolaid","knight1","murphy1","volcano","idunno","2005","2233","blueberr","biguns","yamahar1","zapper","zorro1","0911","3006","sixsix","shopper","sextoy","snowboard","speedway","pokey","playboy2","titi","toonarmy","lambda","joecool","juniper","max123","mariposa","met2002","reggae","ricky1","1236","1228","1016","all4one","baberuth","asgard","484848","5683","6669","catnip","charisma","capslock","cashmone","galant","frenchy","gizmodo1","girlies","screwy","doubled","divers","dte4uw","dragonfl","treble","twinkie","tropical","crescent","cococo","dabomb","daffy","dandfa","cyrano","nathanie","boners","helium","hellas","espresso","killa","kikimora","w4g8at","ilikeit","iforget","1944","20002000","birthday1","beatles1","blue1","bigdicks","beethove","blacklab","blazers","benny1","woodwork","0069","0101","taffy","4567","shodan","pavlov","pinnacle","petunia","tito","teenie","lemonade","lalakers","lebowski","lalalala","ladyboy","jeeper","joyjoy","mercury1","mantle","mannn","rocknrol","riversid","123aaa","11112222","121314","1021","1004","1120","allen1","ambers","amstel","alice1","alleycat","allegro","ambrosia","gspot","goodsex","hattrick","harpoon","878787","8inches","4wwvte","cassandr","charlie123","gatsby","generic","gareth","fuckme2","samm","seadog","satchmo","scxakv","santafe","dipper","outoutout","madmad","london1","qbg26i","pussy123","tzpvaw","vamp","comp","cowgirl","coldplay","dawgs","nt5d27","novifarm","notredam","newness","mykids","bryan1","bouncer","hihihi","honeybee","iceman1","hotlips","dynamo","kappa","kahlua","muffy","mizzou","wannabe","wednesda","whatup","waterfal","willy1","bear1","billabon","youknow","yyyyyy1","zachary1","01234567","070462","zurich","superstar","stiletto","strat","427900","sigmachi","shells","sexy123","smile1","sophie1","stayout","somerset","playmate","pinkfloyd","phish1","payday","thebear","telefon","laetitia","kswbdu","jerky","metro","revoluti","1216","1201","1204","1222","1115","archange","barry1","handball","676767","chewbacc","furball","gocubs","fullback","gman","dewalt","dominiqu","diver1","dhip6a","olemiss","mandrake","mangos","pretzel","pusssy","tripleh","vagabond","clovis","dandan","csfbr5yy","deadspin","ninguna","ncc74656","bootsie","bp2002","bourbon","bumble","heyyou","houston1","hemlock","hippo","hornets","horseman","excess","extensa","muffin1","virginie","werdna","idontknow","jack1","1bitch","151nxjmt","bendover","bmwbmw","zaq123","wxcvbn","supernov","tahoe","shakur","sexyone","seviyi","smart1","speed1","pepito","phantom1","playoffs","terry1","terrier","laser1","lite","lancia","johngalt","jenjen","midori","maserati","matteo","miami1","riffraff","ronald1","1218","1026","123987","1015","1103","armada","architec","austria","gotmilk","cambridg","camero","flex","foreplay","getoff","glacier","glotest","froggie","gerbil","rugger","sanity72","donna1","orchard","oyster","palmtree","pajero","m5wkqf","magenta","luckyone","treefrog","vantage","usmarine","tyvugq","uptown","abacab","aaaaaa1","chuck1","darkange","cyclones","navajo","bubba123","iawgk2","hrfzlz","dylan1","enrico","encore","eclipse1","mutant","mizuno","mustang2","video1","viewer","weed420","whales","jaguar1","1990","159159","1love","bears1","bigtruck","bigboss","blitz","xqgann","yeahyeah","zeke","zardoz","stickman","3825","sentra","shiva","skipper1","singapor","southpaw","sonora","squid","slamdunk","slimjim","placid","photon","placebo","pearl1","test12","therock1","tiger123","leinad","legman","jeepers","joeblow","mike23","redcar","rhinos","rjw7x4","1102","13576479","112211","gwju3g","greywolf","7bgiqk","7878","535353","4snz9g","candyass","cccccc1","catfight","cali","fister","fosters","finland","frankie1","gizzmo","royalty","rugrat","dodo","oemdlg","out3xf","paddy","opennow","puppy1","qazwsxedc","ramjet","abraxas","cn42qj","dancer1","death666","nudity","nimda2k","buick","bobb","braves1","henrik","hooligan","everlast","karachi","mortis","monies","motocros","wally1","willie1","inspiron","1test","2929","bigblack","xytfu7","yackwin","zaq1xsw2","yy5rbfsc","100100","0660","tahiti","takehana","332211","3535","sedona","seawolf","skydiver","spleen","slash","spjfet","special1","slimshad","sopranos","spock1","penis1","patches1","thierry","thething","toohot","limpone","mash4077","matchbox","masterp","maxdog","ribbit","rockin","redhat","1113","14789632","1331","allday","aladin","andrey","amethyst","baseball1","athome","goofy1","greenman","goofball","ha8fyp","goodday","778899","charon","chappy","caracas","cardiff","capitals","canada1","cajun","catter","freddy1","favorite2","forme","forsaken","feelgood","gfxqx686","saskia","sanjose","salsa","dilbert1","dukeduke","downhill","longhair","locutus","lockdown","malachi","mamacita","lolipop","rainyday","pumpkin1","punker","prospect","rambo1","rainbows","quake","trinity1","trooper1","citation","coolcat","default","deniro","d9ungl","daddys","nautica","nermal","bukowski","bubbles1","bogota","buds","hulk","hitachi","ender","export","kikiki","kcchiefs","kram","morticia","montrose","mongo","waqw3p","wizzard","whdbtp","whkzyc","154ugeiu","1fuck","binky","bigred1","blubber","becky1","year2005","wonderfu","xrated","0001","tampabay","survey","tammy1","stuffer","3mpz4r","3000","3some","sierra1","shampoo","shyshy","slapnuts","standby","spartan1","sprocket","stanley1","poker1","theshit","lavalamp","light1","laserjet","jediknig","jjjjj1","mazda626","menthol","margaux","medic1","rhino1","1209","1234321","amigos","apricot","asdfgh1","hairball","hatter","grimace","7xm5rq","6789","cartoons","capcom","cashflow","carrots","fanatic","format","girlie","safeway","dogfart","dondon","outsider","odin","opiate","lollol","love12","mallrats","prague","primetime21","pugsley","r29hqq","valleywa","airman","abcdefg1","darkone","cummer","natedogg","nineball","ndeyl5","natchez","newone","normandy","nicetits","buddy123","buddys","homely","husky","iceland","hr3ytm","highlife","holla","earthlin","exeter","eatmenow","kimkim","k2trix","kernel","money123","moonman","miles1","mufasa","mousey","whites","warhamme","jackass1","2277","20spanks","blobby","blinky","bikers","blackjack","becca","blue23","xman","wyvern","085tzzqi","zxzxzx","zsmj2v","suede","t26gn4","sugars","tantra","swoosh","4226","4271","321123","383pdjvl","shane1","shelby1","spades","smother","sparhawk","pisser","photo1","pebble","peavey","pavement","thistle","kronos","lilbit","linux","melanie1","marbles","redlight","1208","1138","1008","alchemy","aolsucks","alexalex","atticus","auditt","b929ezzh","goodyear","gubber","863abgsg","7474","797979","464646","543210","4zqauf","4949","ch5nmk","carlito","chewey","carebear","checkmat","cheddar","chachi","forgetit","forlife","giants1","getit","gerhard","galileo","g3ujwg","ganja","rufus1","rushmore","discus","dudeman","olympus","oscars","osprey","madcow","locust","loyola","mammoth","proton","rabbit1","ptfe3xxp","pwxd5x","purple1","punkass","prophecy","uyxnyd","tyson1","aircraft","access99","abcabc","colts","civilwar","claudia1","contour","dddddd1","cypher","dapzu455","daisydog","noles","hoochie","hoser","eldiablo","kingrich","mudvayne","motown","mp8o6d","vipergts","italiano","2055","2211","bloke","blade1","yamato","zooropa","yqlgr667","050505","zxcvbnm1","zw6syj","suckcock","tango1","swampy","445566","333666","380zliki","sexpot","sexylady","sixtynin","sickboy","spiffy","skylark","sparkles","pintail","phreak","teller","timtim","thighs","latex","letsdoit","lkjhg","landmark","lizzard","marlins","marauder","metal1","manu","righton","1127","alain","alcat","amigo","basebal1","azertyui","azrael","hamper","gotenks","golfgti","hawkwind","h2slca","grace1","6chid8","789654","canine","casio","cazzo","cbr900","cabrio","calypso","capetown","feline","flathead","fisherma","flipmode","fungus","g9zns4","giggle","gabriel1","fuck123","saffron","dogmeat","dreamcas","dirtydog","douche","dresden","dickdick","destiny1","pappy","oaktree","luft4","puta","ramada","trumpet1","vcradq","tulip","tracy71","tycoon","aaaaaaa1","conquest","chitown","creepers","cornhole","danman","dada","density","d9ebk7","darth","nirvana1","nestle","brenda1","bonanza","hotspur","hufmqw","electro","erasure","elisabet","etvww4","ewyuza","eric1","kenken","kismet","klaatu","milamber","willi","isacs155","igor","1million","1letmein","x35v8l","yogi","ywvxpz","xngwoj","zippy1","020202","****","stonewal","sentry","sexsexsex","sonysony","smirnoff","star12","solace","star1","pkxe62","pilot1","pommes","paulpaul","tical","tictac","lighthou","lemans","kubrick","letmein22","letmesee","jys6wz","jonesy","jjjjjj1","jigga","redstorm","riley1","14141414","1126","allison1","badboy1","asthma","auggie","hardwood","gumbo","616913","57np39","56qhxs","4mnveh","fatluvr69","fqkw5m","fidelity","feathers","fresno","godiva","gecko","gibson1","gogators","general1","saxman","rowing","sammys","scotts","scout1","sasasa","samoht","dragon69","ducky","dragonball","driller","p3wqaw","papillon","oneone","openit","optimist","longshot","rapier","pussy2","ralphie","tuxedo","undertow","copenhag","delldell","culinary","deltas","mytime","noname","noles1","bucker","bopper","burnout","ibilltes","hihje863","hitter","ekim","espana","eatme69","elpaso","express1","eeeeee1","eatme1","karaoke","mustang5","wellingt","willem","waterski","webcam","jasons","infinite","iloveyou!","jakarta","belair","bigdad","beerme","yoshi","yinyang","x24ik3","063dyjuy","0000007","ztmfcq","stopit","stooges","symow8","strato","2hot4u","skins","shakes","sex1","snacks","softtail","slimed123","pizzaman","tigercat","tonton","lager","lizzy","juju","john123","jesse1","jingles","martian","mario1","rootedit","rochard","redwine","requiem","riverrat","1117","1014","1205","amor","amiga","alpina","atreides","banana1","bahamut","golfman","happines","7uftyx","5432","5353","5151","4747","foxfire","ffvdj474","foreskin","gayboy","gggggg1","gameover","glitter","funny1","scoobydoo","saxophon","dingbat","digimon","omicron","panda1","loloxx","macintos","lululu","lollypop","racer1","queen1","qwertzui","upnfmc","tyrant","trout1","9skw5g","aceman","acls2h","aaabbb","acapulco","aggie","comcast","cloudy","cq2kph","d6o8pm","cybersex","davecole","darian","crumbs","davedave","dasani","mzepab","myporn","narnia","booger1","bravo1","budgie","btnjey","highlander","hotel6","humbug","ewtosi","kristin1","kobe","knuckles","keith1","katarina","muff","muschi","montana1","wingchun","wiggle","whatthe","vette1","vols","virago","intj3a","ishmael","jachin","illmatic","199999","2010","blender","bigpenis","bengal","blue1234","zaqxsw","xray","xxxxxxx1","zebras","yanks","tadpole","stripes","3737","4343","3728","4444444","368ejhih","solar","sonne","sniffer","sonata","squirts","playstation","pktmxr","pescator","texaco","lesbos","l8v53x","jo9k2jw2","jimbeam","jimi","jupiter2","jurassic","marines1","rocket1","14725836","12345679","1219","123098","1233","alessand","althor","arch","alpha123","basher","barefeet","balboa","bbbbb1","badabing","gopack","golfnut","gsxr1000","gregory1","766rglqy","8520","753159","8dihc6","69camaro","666777","cheeba","chino","cheeky","camel1","fishcake","flubber","gianni","gnasher23","frisbee","fuzzy1","fuzzball","save13tx","russell1","sandra1","scrotum","scumbag","sabre","samdog","dripping","dragon12","dragster","orwell","mainland","maine","qn632o","poophead","rapper","porn4life","rapunzel","velocity","vanessa1","trueblue","vampire1","abacus","902100","crispy","chooch","d6wnro","dabulls","dehpye","navyseal","njqcw4","nownow","nigger1","nightowl","nonenone","nightmar","bustle","buddy2","boingo","bugman","bosshog","hybrid","hillside","hilltop","hotlegs","hzze929b","hhhhh1","hellohel","evilone","edgewise","e5pftu","eded","embalmer","excalibur","elefant","kenzie","killah","kleenex","mouses","mounta1n","motors","mutley","muffdive","vivitron","w00t88","iloveit","jarjar","incest","indycar","17171717","1664","17011701","222777","2663","beelch","benben","yitbos","yyyyy1","zzzzz1","stooge","tangerin","taztaz","stewart1","summer69","system1","surveyor","stirling","3qvqod","3way","456321","sizzle","simhrq","sparty","ssptx452","sphere","persian","ploppy","pn5jvw","poobear","pianos","plaster","testme","tiff","thriller","master12","rockey","1229","1217","1478","1009","anastasi","amonra","argentin","albino","azazel","grinder","6uldv8","83y6pv","8888888","4tlved","515051","carsten","flyers88","ffffff1","firehawk","firedog","flashman","ggggg1","godspeed","galway","giveitup","funtimes","gohan","giveme","geryfe","frenchie","sayang","rudeboy","sandals","dougal","drag0n","dga9la","desktop","onlyone","otter","pandas","mafia","luckys","lovelife","manders","qqh92r","qcmfd454","radar1","punani","ptbdhw","turtles","undertaker","trs8f7","ugejvp","abba","911turbo","acdc","abcd123","crash1","colony","delboy","davinci","notebook","nitrox","borabora","bonzai","brisbane","heeled","hooyah","hotgirl","i62gbq","horse1","hpk2qc","epvjb6","mnbvc","mommy1","munster","wiccan","2369","bettyboo","blondy","bismark","beanbag","bjhgfi","blackice","yvtte545","ynot","yess","zlzfrh","wolvie","007bond","******","tailgate","tanya1","sxhq65","stinky1","3234412","3ki42x","seville","shimmer","sienna","shitshit","skillet","sooners1","solaris","smartass","pedros","pennywis","pfloyd","tobydog","thetruth","letme1n","mario66","micky","rocky2","rewq","reindeer","1128","1207","1104","1432","aprilia","allstate","bagels","baggies","barrage","guru","72d5tn","606060","4wcqjn","chance1","flange","fartman","geil","gbhcf2","fussball","fuaqz4","gameboy","geneviev","rotary","seahawk","saab","samadams","devlt4","ditto","drevil","drinker","deuce","dipstick","octopus","ottawa","losangel","loverman","porky","q9umoz","rapture","pussy4me","triplex","ue8fpw","turbos","aaa340","churchil","crazyman","cutiepie","ddddd1","dejavu","cuxldv","nbvibt","nikon","niko","nascar1","bubba2","boobear","boogers","bullwink","bulldawg","horsemen","escalade","eagle2","dynamic","efyreg","minnesot","mogwai","msnxbi","mwq6qlzo","werder","verygood","voodoo1","iiiiii1","159951","1624","1911a1","2244","bellagio","bedlam","belkin","bill1","xirt2k","??????","susieq","sundown","sukebe","swifty","2fast4u","sexe","shroom","seaweed","skeeter1","snicker","spanky1","spook","phaedrus","pilots","peddler","thumper1","tiger7","tmjxn151","thematri","l2g7k3","letmeinn","jeffjeff","johnmish","mantra","mike69","mazda6","riptide","robots","1107","1130","142857","11001001","1134","armored","allnight","amatuers","bartok","astral","baboon","balls1","bassoon","hcleeb","happyman","granite","graywolf","golf1","gomets","8vjzus","7890","789123","8uiazp","5757","474jdvff","551scasi","50cent","camaro1","cherry1","chemist","firenze","fishtank","freewill","glendale","frogfrog","ganesh","scirocco","devilman","doodles","okinawa","olympic","orpheus","ohmygod","paisley","pallmall","lunchbox","manhatta","mahalo","mandarin","qwqwqw","qguvyt","pxx3eftp","rambler","poppy1","turk182","vdlxuc","tugboat","valiant","uwrl7c","chris123","cmfnpu","decimal","debbie1","dandy","daedalus","natasha1","nissan1","nancy123","nevermin","napalm","newcastle","bonghit","ibxnsm","hhhhhh1","holger","edmonton","equinox","dvader","kimmy","knulla","mustafa","monsoon","mistral","morgana","monica1","mojave","monterey","mrbill","vkaxcs","victor1","violator","vfdhif","wilson1","wavpzt","wildstar","winter99","iqzzt580","imback","1914","19741974","1monkey","1q2w3e4r5t","2500","2255","bigshow","bigbucks","blackcoc","zoomer","wtcacq","wobble","xmen","xjznq5","yesterda","yhwnqc","zzzxxx","393939","2fchbg","skinhead","skilled","shadow12","seaside","sinful","silicon","smk7366","snapshot","sniper1","soccer11","smutty","peepers","plokij","pdiddy","pimpdaddy","thrust","terran","topaz","today1","lionhear","littlema","lauren1","lincoln1","lgnu9d","juneau","methos","rogue1","romulus","redshift","1202","1469","12locked","arizona1","alfarome","al9agd","aol123","altec","apollo1","arse","baker1","bbb747","axeman","astro1","hawthorn","goodfell","hawks1","gstring","hannes","8543852","868686","4ng62t","554uzpad","5401","567890","5232","catfood","fire1","flipflop","fffff1","fozzie","fluff","fzappa","rustydog","scarab","satin","ruger","samsung1","destin","diablo2","dreamer1","detectiv","doqvq3","drywall","paladin1","papabear","offroad","panasonic","nyyankee","luetdi","qcfmtz","pyf8ah","puddles","pussyeat","ralph1","princeto","trivia","trewq","tri5a3","advent","9898","agyvorc","clarkie","coach1","courier","christo","chowder","cyzkhw","davidb","dad2ownu","daredevi","de7mdf","nazgul","booboo1","bonzo","butch1","huskers1","hgfdsa","hornyman","elektra","england1","elodie","kermit1","kaboom","morten","mocha","monday1","morgoth","weewee","weenie","vorlon","wahoo","ilovegod","insider","jayman","1911","1dallas","1900","1ranger","201jedlz","2501","1qaz","bignuts","bigbad","beebee","billows","belize","wvj5np","wu4etd","yamaha1","wrinkle5","zebra1","yankee1","zoomzoom","09876543","0311","?????","stjabn","tainted","3tmnej","skooter","skelter","starlite","spice1","stacey1","smithy","pollux","peternorth","pixie","piston","poets","toons","topspin","kugm7b","legends","jeepjeep","joystick","junkmail","jojojojo","jonboy","midland","mayfair","riches","reznor","rockrock","reboot","renee1","roadway","rasta220","1411","1478963","1019","archery","andyandy","barks","bagpuss","auckland","gooseman","hazmat","gucci","grammy","happydog","7kbe9d","7676","6bjvpe","5lyedn","5858","5291","charlie2","c7lrwu","candys","chateau","ccccc1","cardinals","fihdfv","fortune12","gocats","gaelic","fwsadn","godboy","gldmeo","fx3tuo","fubar1","generals","gforce","rxmtkp","rulz","sairam","dunhill","dogggg","ozlq6qwm","ov3ajy","lockout","makayla","macgyver","mallorca","prima","pvjegu","qhxbij","prelude1","totoro","tusymo","trousers","tulane","turtle1","tracy1","aerosmit","abbey1","clticic","cooper1","comets","delpiero","cyprus","dante1","dave1","nounours","nexus6","nogard","norfolk","brent1","booyah","bootleg","bulls23","bulls1","booper","heretic","icecube","hellno","hounds","honeydew","hooters1","hoes","hevnm4","hugohugo","epson","evangeli","eeeee1","eyphed"]} 2 | -------------------------------------------------------------------------------- /data/data/Qwerty.json: -------------------------------------------------------------------------------- 1 | { 2 | "Graph": { 3 | "!": [ 4 | "`~", 5 | null, 6 | null, 7 | "2@", 8 | "qQ", 9 | null 10 | ], 11 | "\"": [ 12 | ";:", 13 | "[{", 14 | "]}", 15 | null, 16 | null, 17 | "/?" 18 | ], 19 | "#": [ 20 | "2@", 21 | null, 22 | null, 23 | "4$", 24 | "eE", 25 | "wW" 26 | ], 27 | "$": [ 28 | "3#", 29 | null, 30 | null, 31 | "5%", 32 | "rR", 33 | "eE" 34 | ], 35 | "%": [ 36 | "4$", 37 | null, 38 | null, 39 | "6^", 40 | "tT", 41 | "rR" 42 | ], 43 | "&": [ 44 | "6^", 45 | null, 46 | null, 47 | "8*", 48 | "uU", 49 | "yY" 50 | ], 51 | "'": [ 52 | ";:", 53 | "[{", 54 | "]}", 55 | null, 56 | null, 57 | "/?" 58 | ], 59 | "(": [ 60 | "8*", 61 | null, 62 | null, 63 | "0)", 64 | "oO", 65 | "iI" 66 | ], 67 | ")": [ 68 | "9(", 69 | null, 70 | null, 71 | "-_", 72 | "pP", 73 | "oO" 74 | ], 75 | "*": [ 76 | "7&", 77 | null, 78 | null, 79 | "9(", 80 | "iI", 81 | "uU" 82 | ], 83 | "+": [ 84 | "-_", 85 | null, 86 | null, 87 | null, 88 | "]}", 89 | "[{" 90 | ], 91 | ",": [ 92 | "mM", 93 | "kK", 94 | "lL", 95 | ".>", 96 | null, 97 | null 98 | ], 99 | "-": [ 100 | "0)", 101 | null, 102 | null, 103 | "=+", 104 | "[{", 105 | "pP" 106 | ], 107 | ".": [ 108 | ",<", 109 | "lL", 110 | ";:", 111 | "/?", 112 | null, 113 | null 114 | ], 115 | "/": [ 116 | ".>", 117 | ";:", 118 | "'\"", 119 | null, 120 | null, 121 | null 122 | ], 123 | "0": [ 124 | "9(", 125 | null, 126 | null, 127 | "-_", 128 | "pP", 129 | "oO" 130 | ], 131 | "1": [ 132 | "`~", 133 | null, 134 | null, 135 | "2@", 136 | "qQ", 137 | null 138 | ], 139 | "2": [ 140 | "1!", 141 | null, 142 | null, 143 | "3#", 144 | "wW", 145 | "qQ" 146 | ], 147 | "3": [ 148 | "2@", 149 | null, 150 | null, 151 | "4$", 152 | "eE", 153 | "wW" 154 | ], 155 | "4": [ 156 | "3#", 157 | null, 158 | null, 159 | "5%", 160 | "rR", 161 | "eE" 162 | ], 163 | "5": [ 164 | "4$", 165 | null, 166 | null, 167 | "6^", 168 | "tT", 169 | "rR" 170 | ], 171 | "6": [ 172 | "5%", 173 | null, 174 | null, 175 | "7&", 176 | "yY", 177 | "tT" 178 | ], 179 | "7": [ 180 | "6^", 181 | null, 182 | null, 183 | "8*", 184 | "uU", 185 | "yY" 186 | ], 187 | "8": [ 188 | "7&", 189 | null, 190 | null, 191 | "9(", 192 | "iI", 193 | "uU" 194 | ], 195 | "9": [ 196 | "8*", 197 | null, 198 | null, 199 | "0)", 200 | "oO", 201 | "iI" 202 | ], 203 | ":": [ 204 | "lL", 205 | "pP", 206 | "[{", 207 | "'\"", 208 | "/?", 209 | ".>" 210 | ], 211 | ";": [ 212 | "lL", 213 | "pP", 214 | "[{", 215 | "'\"", 216 | "/?", 217 | ".>" 218 | ], 219 | "<": [ 220 | "mM", 221 | "kK", 222 | "lL", 223 | ".>", 224 | null, 225 | null 226 | ], 227 | "=": [ 228 | "-_", 229 | null, 230 | null, 231 | null, 232 | "]}", 233 | "[{" 234 | ], 235 | ">": [ 236 | ",<", 237 | "lL", 238 | ";:", 239 | "/?", 240 | null, 241 | null 242 | ], 243 | "?": [ 244 | ".>", 245 | ";:", 246 | "'\"", 247 | null, 248 | null, 249 | null 250 | ], 251 | "@": [ 252 | "1!", 253 | null, 254 | null, 255 | "3#", 256 | "wW", 257 | "qQ" 258 | ], 259 | "A": [ 260 | null, 261 | "qQ", 262 | "wW", 263 | "sS", 264 | "zZ", 265 | null 266 | ], 267 | "B": [ 268 | "vV", 269 | "gG", 270 | "hH", 271 | "nN", 272 | null, 273 | null 274 | ], 275 | "C": [ 276 | "xX", 277 | "dD", 278 | "fF", 279 | "vV", 280 | null, 281 | null 282 | ], 283 | "D": [ 284 | "sS", 285 | "eE", 286 | "rR", 287 | "fF", 288 | "cC", 289 | "xX" 290 | ], 291 | "E": [ 292 | "wW", 293 | "3#", 294 | "4$", 295 | "rR", 296 | "dD", 297 | "sS" 298 | ], 299 | "F": [ 300 | "dD", 301 | "rR", 302 | "tT", 303 | "gG", 304 | "vV", 305 | "cC" 306 | ], 307 | "G": [ 308 | "fF", 309 | "tT", 310 | "yY", 311 | "hH", 312 | "bB", 313 | "vV" 314 | ], 315 | "H": [ 316 | "gG", 317 | "yY", 318 | "uU", 319 | "jJ", 320 | "nN", 321 | "bB" 322 | ], 323 | "I": [ 324 | "uU", 325 | "8*", 326 | "9(", 327 | "oO", 328 | "kK", 329 | "jJ" 330 | ], 331 | "J": [ 332 | "hH", 333 | "uU", 334 | "iI", 335 | "kK", 336 | "mM", 337 | "nN" 338 | ], 339 | "K": [ 340 | "jJ", 341 | "iI", 342 | "oO", 343 | "lL", 344 | ",<", 345 | "mM" 346 | ], 347 | "L": [ 348 | "kK", 349 | "oO", 350 | "pP", 351 | ";:", 352 | ".>", 353 | ",<" 354 | ], 355 | "M": [ 356 | "nN", 357 | "jJ", 358 | "kK", 359 | ",<", 360 | null, 361 | null 362 | ], 363 | "N": [ 364 | "bB", 365 | "hH", 366 | "jJ", 367 | "mM", 368 | null, 369 | null 370 | ], 371 | "O": [ 372 | "iI", 373 | "9(", 374 | "0)", 375 | "pP", 376 | "lL", 377 | "kK" 378 | ], 379 | "P": [ 380 | "oO", 381 | "0)", 382 | "-_", 383 | "[{", 384 | ";:", 385 | "lL" 386 | ], 387 | "Q": [ 388 | null, 389 | "1!", 390 | "2@", 391 | "wW", 392 | "aA", 393 | null 394 | ], 395 | "R": [ 396 | "eE", 397 | "4$", 398 | "5%", 399 | "tT", 400 | "fF", 401 | "dD" 402 | ], 403 | "S": [ 404 | "aA", 405 | "wW", 406 | "eE", 407 | "dD", 408 | "xX", 409 | "zZ" 410 | ], 411 | "T": [ 412 | "rR", 413 | "5%", 414 | "6^", 415 | "yY", 416 | "gG", 417 | "fF" 418 | ], 419 | "U": [ 420 | "yY", 421 | "7&", 422 | "8*", 423 | "iI", 424 | "jJ", 425 | "hH" 426 | ], 427 | "V": [ 428 | "cC", 429 | "fF", 430 | "gG", 431 | "bB", 432 | null, 433 | null 434 | ], 435 | "W": [ 436 | "qQ", 437 | "2@", 438 | "3#", 439 | "eE", 440 | "sS", 441 | "aA" 442 | ], 443 | "X": [ 444 | "zZ", 445 | "sS", 446 | "dD", 447 | "cC", 448 | null, 449 | null 450 | ], 451 | "Y": [ 452 | "tT", 453 | "6^", 454 | "7&", 455 | "uU", 456 | "hH", 457 | "gG" 458 | ], 459 | "Z": [ 460 | null, 461 | "aA", 462 | "sS", 463 | "xX", 464 | null, 465 | null 466 | ], 467 | "[": [ 468 | "pP", 469 | "-_", 470 | "=+", 471 | "]}", 472 | "'\"", 473 | ";:" 474 | ], 475 | "\\": [ 476 | "]}", 477 | null, 478 | null, 479 | null, 480 | null, 481 | null 482 | ], 483 | "]": [ 484 | "[{", 485 | "=+", 486 | null, 487 | "\\|", 488 | null, 489 | "'\"" 490 | ], 491 | "^": [ 492 | "5%", 493 | null, 494 | null, 495 | "7&", 496 | "yY", 497 | "tT" 498 | ], 499 | "_": [ 500 | "0)", 501 | null, 502 | null, 503 | "=+", 504 | "[{", 505 | "pP" 506 | ], 507 | "`": [ 508 | null, 509 | null, 510 | null, 511 | "1!", 512 | null, 513 | null 514 | ], 515 | "a": [ 516 | null, 517 | "qQ", 518 | "wW", 519 | "sS", 520 | "zZ", 521 | null 522 | ], 523 | "b": [ 524 | "vV", 525 | "gG", 526 | "hH", 527 | "nN", 528 | null, 529 | null 530 | ], 531 | "c": [ 532 | "xX", 533 | "dD", 534 | "fF", 535 | "vV", 536 | null, 537 | null 538 | ], 539 | "d": [ 540 | "sS", 541 | "eE", 542 | "rR", 543 | "fF", 544 | "cC", 545 | "xX" 546 | ], 547 | "e": [ 548 | "wW", 549 | "3#", 550 | "4$", 551 | "rR", 552 | "dD", 553 | "sS" 554 | ], 555 | "f": [ 556 | "dD", 557 | "rR", 558 | "tT", 559 | "gG", 560 | "vV", 561 | "cC" 562 | ], 563 | "g": [ 564 | "fF", 565 | "tT", 566 | "yY", 567 | "hH", 568 | "bB", 569 | "vV" 570 | ], 571 | "h": [ 572 | "gG", 573 | "yY", 574 | "uU", 575 | "jJ", 576 | "nN", 577 | "bB" 578 | ], 579 | "i": [ 580 | "uU", 581 | "8*", 582 | "9(", 583 | "oO", 584 | "kK", 585 | "jJ" 586 | ], 587 | "j": [ 588 | "hH", 589 | "uU", 590 | "iI", 591 | "kK", 592 | "mM", 593 | "nN" 594 | ], 595 | "k": [ 596 | "jJ", 597 | "iI", 598 | "oO", 599 | "lL", 600 | ",<", 601 | "mM" 602 | ], 603 | "l": [ 604 | "kK", 605 | "oO", 606 | "pP", 607 | ";:", 608 | ".>", 609 | ",<" 610 | ], 611 | "m": [ 612 | "nN", 613 | "jJ", 614 | "kK", 615 | ",<", 616 | null, 617 | null 618 | ], 619 | "n": [ 620 | "bB", 621 | "hH", 622 | "jJ", 623 | "mM", 624 | null, 625 | null 626 | ], 627 | "o": [ 628 | "iI", 629 | "9(", 630 | "0)", 631 | "pP", 632 | "lL", 633 | "kK" 634 | ], 635 | "p": [ 636 | "oO", 637 | "0)", 638 | "-_", 639 | "[{", 640 | ";:", 641 | "lL" 642 | ], 643 | "q": [ 644 | null, 645 | "1!", 646 | "2@", 647 | "wW", 648 | "aA", 649 | null 650 | ], 651 | "r": [ 652 | "eE", 653 | "4$", 654 | "5%", 655 | "tT", 656 | "fF", 657 | "dD" 658 | ], 659 | "s": [ 660 | "aA", 661 | "wW", 662 | "eE", 663 | "dD", 664 | "xX", 665 | "zZ" 666 | ], 667 | "t": [ 668 | "rR", 669 | "5%", 670 | "6^", 671 | "yY", 672 | "gG", 673 | "fF" 674 | ], 675 | "u": [ 676 | "yY", 677 | "7&", 678 | "8*", 679 | "iI", 680 | "jJ", 681 | "hH" 682 | ], 683 | "v": [ 684 | "cC", 685 | "fF", 686 | "gG", 687 | "bB", 688 | null, 689 | null 690 | ], 691 | "w": [ 692 | "qQ", 693 | "2@", 694 | "3#", 695 | "eE", 696 | "sS", 697 | "aA" 698 | ], 699 | "x": [ 700 | "zZ", 701 | "sS", 702 | "dD", 703 | "cC", 704 | null, 705 | null 706 | ], 707 | "y": [ 708 | "tT", 709 | "6^", 710 | "7&", 711 | "uU", 712 | "hH", 713 | "gG" 714 | ], 715 | "z": [ 716 | null, 717 | "aA", 718 | "sS", 719 | "xX", 720 | null, 721 | null 722 | ], 723 | "{": [ 724 | "pP", 725 | "-_", 726 | "=+", 727 | "]}", 728 | "'\"", 729 | ";:" 730 | ], 731 | "|": [ 732 | "]}", 733 | null, 734 | null, 735 | null, 736 | null, 737 | null 738 | ], 739 | "}": [ 740 | "[{", 741 | "=+", 742 | null, 743 | "\\|", 744 | null, 745 | "'\"" 746 | ], 747 | "~": [ 748 | null, 749 | null, 750 | null, 751 | "1!", 752 | null, 753 | null 754 | ] 755 | } 756 | } 757 | -------------------------------------------------------------------------------- /entropy/entropyCalculator.go: -------------------------------------------------------------------------------- 1 | package entropy 2 | 3 | import ( 4 | "github.com/nbutton23/zxcvbn-go/adjacency" 5 | "github.com/nbutton23/zxcvbn-go/match" 6 | "github.com/nbutton23/zxcvbn-go/utils/math" 7 | "math" 8 | "regexp" 9 | "unicode" 10 | ) 11 | 12 | const ( 13 | numYears = float64(119) // years match against 1900 - 2019 14 | numMonths = float64(12) 15 | numDays = float64(31) 16 | ) 17 | 18 | var ( 19 | startUpperRx = regexp.MustCompile(`^[A-Z][^A-Z]+$`) 20 | endUpperRx = regexp.MustCompile(`^[^A-Z]+[A-Z]$'`) 21 | allUpperRx = regexp.MustCompile(`^[A-Z]+$`) 22 | keyPadStartingPositions = len(adjacency.GraphMap["keypad"].Graph) 23 | keyPadAvgDegree = adjacency.GraphMap["keypad"].CalculateAvgDegree() 24 | ) 25 | 26 | // DictionaryEntropy calculates the entropy of a dictionary match 27 | func DictionaryEntropy(match match.Match, rank float64) float64 { 28 | baseEntropy := math.Log2(rank) 29 | upperCaseEntropy := extraUpperCaseEntropy(match) 30 | //TODO: L33t 31 | return baseEntropy + upperCaseEntropy 32 | } 33 | 34 | func extraUpperCaseEntropy(match match.Match) float64 { 35 | word := match.Token 36 | 37 | allLower := true 38 | 39 | for _, char := range word { 40 | if unicode.IsUpper(char) { 41 | allLower = false 42 | break 43 | } 44 | } 45 | if allLower { 46 | return float64(0) 47 | } 48 | 49 | //a capitalized word is the most common capitalization scheme, 50 | //so it only doubles the search space (uncapitalized + capitalized): 1 extra bit of entropy. 51 | //allcaps and end-capitalized are common enough too, underestimate as 1 extra bit to be safe. 52 | 53 | for _, matcher := range []*regexp.Regexp{startUpperRx, endUpperRx, allUpperRx} { 54 | if matcher.MatchString(word) { 55 | return float64(1) 56 | } 57 | } 58 | //Otherwise calculate the number of ways to capitalize U+L uppercase+lowercase letters with U uppercase letters or 59 | //less. Or, if there's more uppercase than lower (for e.g. PASSwORD), the number of ways to lowercase U+L letters 60 | //with L lowercase letters or less. 61 | 62 | countUpper, countLower := float64(0), float64(0) 63 | for _, char := range word { 64 | if unicode.IsUpper(char) { 65 | countUpper++ 66 | } else if unicode.IsLower(char) { 67 | countLower++ 68 | } 69 | } 70 | totalLenght := countLower + countUpper 71 | var possibililities float64 72 | 73 | for i := float64(0); i <= math.Min(countUpper, countLower); i++ { 74 | possibililities += float64(zxcvbnmath.NChoseK(totalLenght, i)) 75 | } 76 | 77 | if possibililities < 1 { 78 | return float64(1) 79 | } 80 | 81 | return float64(math.Log2(possibililities)) 82 | } 83 | 84 | // SpatialEntropy calculates the entropy for spatial matches 85 | func SpatialEntropy(match match.Match, turns int, shiftCount int) float64 { 86 | var s, d float64 87 | if match.DictionaryName == "qwerty" || match.DictionaryName == "dvorak" { 88 | //todo: verify qwerty and dvorak have the same length and degree 89 | s = float64(len(adjacency.BuildQwerty().Graph)) 90 | d = adjacency.BuildQwerty().CalculateAvgDegree() 91 | } else { 92 | s = float64(keyPadStartingPositions) 93 | d = keyPadAvgDegree 94 | } 95 | 96 | possibilities := float64(0) 97 | 98 | length := float64(len(match.Token)) 99 | 100 | //TODO: Should this be <= or just < ? 101 | //Estimate the number of possible patterns w/ length L or less with t turns or less 102 | for i := float64(2); i <= length+1; i++ { 103 | possibleTurns := math.Min(float64(turns), i-1) 104 | for j := float64(1); j <= possibleTurns+1; j++ { 105 | x := zxcvbnmath.NChoseK(i-1, j-1) * s * math.Pow(d, j) 106 | possibilities += x 107 | } 108 | } 109 | 110 | entropy := math.Log2(possibilities) 111 | //add extra entropu for shifted keys. ( % instead of 5 A instead of a) 112 | //Math is similar to extra entropy for uppercase letters in dictionary matches. 113 | 114 | if S := float64(shiftCount); S > float64(0) { 115 | possibilities = float64(0) 116 | U := length - S 117 | 118 | for i := float64(0); i < math.Min(S, U)+1; i++ { 119 | possibilities += zxcvbnmath.NChoseK(S+U, i) 120 | } 121 | 122 | entropy += math.Log2(possibilities) 123 | } 124 | 125 | return entropy 126 | } 127 | 128 | // RepeatEntropy calculates the entropy for repeating entropy 129 | func RepeatEntropy(match match.Match) float64 { 130 | cardinality := CalcBruteForceCardinality(match.Token) 131 | entropy := math.Log2(cardinality * float64(len(match.Token))) 132 | 133 | return entropy 134 | } 135 | 136 | // CalcBruteForceCardinality calculates the brute force cardinality 137 | //TODO: Validate against python 138 | func CalcBruteForceCardinality(password string) float64 { 139 | lower, upper, digits, symbols := float64(0), float64(0), float64(0), float64(0) 140 | 141 | for _, char := range password { 142 | if unicode.IsLower(char) { 143 | lower = float64(26) 144 | } else if unicode.IsDigit(char) { 145 | digits = float64(10) 146 | } else if unicode.IsUpper(char) { 147 | upper = float64(26) 148 | } else { 149 | symbols = float64(33) 150 | } 151 | } 152 | 153 | cardinality := lower + upper + digits + symbols 154 | return cardinality 155 | } 156 | 157 | // SequenceEntropy calculates the entropy for sequences such as 4567 or cdef 158 | func SequenceEntropy(match match.Match, dictionaryLength int, ascending bool) float64 { 159 | firstChar := match.Token[0] 160 | baseEntropy := float64(0) 161 | if string(firstChar) == "a" || string(firstChar) == "1" { 162 | baseEntropy = float64(0) 163 | } else { 164 | baseEntropy = math.Log2(float64(dictionaryLength)) 165 | //TODO: should this be just the first or any char? 166 | if unicode.IsUpper(rune(firstChar)) { 167 | baseEntropy++ 168 | } 169 | } 170 | 171 | if !ascending { 172 | baseEntropy++ 173 | } 174 | return baseEntropy + math.Log2(float64(len(match.Token))) 175 | } 176 | 177 | // ExtraLeetEntropy calulates the added entropy provied by l33t substitustions 178 | func ExtraLeetEntropy(match match.Match, password string) float64 { 179 | var subsitutions float64 180 | var unsub float64 181 | subPassword := password[match.I:match.J] 182 | for index, char := range subPassword { 183 | if string(char) != string(match.Token[index]) { 184 | subsitutions++ 185 | } else { 186 | //TODO: Make this only true for 1337 chars that are not subs? 187 | unsub++ 188 | } 189 | } 190 | 191 | var possibilities float64 192 | 193 | for i := float64(0); i <= math.Min(subsitutions, unsub)+1; i++ { 194 | possibilities += zxcvbnmath.NChoseK(subsitutions+unsub, i) 195 | } 196 | 197 | if possibilities <= 1 { 198 | return float64(1) 199 | } 200 | return math.Log2(possibilities) 201 | } 202 | 203 | // DateEntropy calculates the entropy provided by a date 204 | func DateEntropy(dateMatch match.DateMatch) float64 { 205 | var entropy float64 206 | if dateMatch.Year < 100 { 207 | entropy = math.Log2(numDays * numMonths * 100) 208 | } else { 209 | entropy = math.Log2(numDays * numMonths * numYears) 210 | } 211 | 212 | if dateMatch.Separator != "" { 213 | entropy += 2 //add two bits for separator selection [/,-,.,etc] 214 | } 215 | return entropy 216 | } 217 | -------------------------------------------------------------------------------- /entropy/entropyCalculator_test.go: -------------------------------------------------------------------------------- 1 | package entropy 2 | 3 | import ( 4 | "github.com/nbutton23/zxcvbn-go/match" 5 | "github.com/stretchr/testify/assert" 6 | "testing" 7 | ) 8 | 9 | func TestDictionaryEntropyCalculation(t *testing.T) { 10 | match := match.Match{ 11 | Pattern: "dictionary", 12 | I: 0, 13 | J: 4, 14 | Token: "first", 15 | } 16 | 17 | entropy := DictionaryEntropy(match, float64(20)) 18 | 19 | assert.Equal(t, 4.321928094887363, entropy) 20 | } 21 | 22 | func TestSpatialEntropyCalculation(t *testing.T) { 23 | matchPlain := match.Match{ 24 | Pattern: "spatial", 25 | I: 0, 26 | J: 5, 27 | Token: "asdfgh", 28 | DictionaryName: "qwerty", 29 | } 30 | entropy := SpatialEntropy(matchPlain, 0, 0) 31 | assert.Equal(t, 9.754887502163468, entropy) 32 | 33 | matchShift := match.Match{ 34 | Pattern: "spatial", 35 | I: 0, 36 | J: 5, 37 | Token: "asdFgh", 38 | DictionaryName: "qwerty", 39 | } 40 | entropyShift := SpatialEntropy(matchShift, 0, 1) 41 | assert.Equal(t, 12.562242424221072, entropyShift) 42 | 43 | matchTurn := match.Match{ 44 | Pattern: "spatial", 45 | I: 0, 46 | J: 5, 47 | Token: "asdcxz", 48 | DictionaryName: "qwerty", 49 | } 50 | entropyTurn := SpatialEntropy(matchTurn, 2, 0) 51 | assert.Equal(t, 14.080500893768884, entropyTurn) 52 | } 53 | 54 | func TestRepeatMatchEntropyCalculation(t *testing.T) { 55 | matchRepeat := match.Match{ 56 | Pattern: "repeat", 57 | I: 0, 58 | J: 4, 59 | Token: "aaaaa", 60 | } 61 | entropy := RepeatEntropy(matchRepeat) 62 | assert.Equal(t, 7.022367813028454, entropy) 63 | } 64 | 65 | func TestSequenceCalculation(t *testing.T) { 66 | matchLower := match.Match{ 67 | Pattern: "sequence", 68 | I: 0, 69 | J: 4, 70 | Token: "jklmn", 71 | } 72 | entropy := SequenceEntropy(matchLower, len("abcdefghijklmnopqrstuvwxyz"), true) 73 | assert.Equal(t, 7.022367813028454, entropy) 74 | 75 | matchUpper := match.Match{ 76 | Pattern: "sequence", 77 | I: 0, 78 | J: 4, 79 | Token: "JKLMN", 80 | } 81 | entropy = SequenceEntropy(matchUpper, len("abcdefghijklmnopqrstuvwxyz"), true) 82 | assert.Equal(t, 8.022367813028454, entropy) 83 | 84 | matchUpperDec := match.Match{ 85 | Pattern: "sequence", 86 | I: 0, 87 | J: 4, 88 | Token: "JKLMN", 89 | } 90 | entropy = SequenceEntropy(matchUpperDec, len("abcdefghijklmnopqrstuvwxyz"), false) 91 | assert.Equal(t, 9.022367813028454, entropy) 92 | 93 | matchDigit := match.Match{ 94 | Pattern: "sequence", 95 | I: 0, 96 | J: 4, 97 | Token: "34567", 98 | } 99 | entropy = SequenceEntropy(matchDigit, 10, true) 100 | assert.Equal(t, 5.643856189774724, entropy) 101 | } 102 | -------------------------------------------------------------------------------- /frequency/frequency.go: -------------------------------------------------------------------------------- 1 | package frequency 2 | 3 | import ( 4 | "encoding/json" 5 | "log" 6 | 7 | "github.com/nbutton23/zxcvbn-go/data" 8 | ) 9 | 10 | // List holds a frequency list 11 | type List struct { 12 | Name string 13 | List []string 14 | } 15 | 16 | // Lists holds all the frequency list in a map 17 | var Lists = make(map[string]List) 18 | 19 | func init() { 20 | maleFilePath := getAsset("data/MaleNames.json") 21 | femaleFilePath := getAsset("data/FemaleNames.json") 22 | surnameFilePath := getAsset("data/Surnames.json") 23 | englishFilePath := getAsset("data/English.json") 24 | passwordsFilePath := getAsset("data/Passwords.json") 25 | 26 | Lists["MaleNames"] = getStringListFromAsset(maleFilePath, "MaleNames") 27 | Lists["FemaleNames"] = getStringListFromAsset(femaleFilePath, "FemaleNames") 28 | Lists["Surname"] = getStringListFromAsset(surnameFilePath, "Surname") 29 | Lists["English"] = getStringListFromAsset(englishFilePath, "English") 30 | Lists["Passwords"] = getStringListFromAsset(passwordsFilePath, "Passwords") 31 | 32 | } 33 | func getAsset(name string) []byte { 34 | data, err := data.Asset(name) 35 | if err != nil { 36 | panic("Error getting asset " + name) 37 | } 38 | 39 | return data 40 | } 41 | func getStringListFromAsset(data []byte, name string) List { 42 | 43 | var tempList List 44 | err := json.Unmarshal(data, &tempList) 45 | if err != nil { 46 | log.Fatal(err) 47 | } 48 | tempList.Name = name 49 | return tempList 50 | } 51 | -------------------------------------------------------------------------------- /fuzz/fuzz.go: -------------------------------------------------------------------------------- 1 | package fuzz 2 | 3 | import ( 4 | "github.com/nbutton23/zxcvbn-go" 5 | ) 6 | 7 | // Fuzz is used to run https://github.com/dvyukov/go-fuzz 8 | func Fuzz(data []byte) int { 9 | password := string(data) 10 | 11 | _ = zxcvbn.PasswordStrength(password, nil) 12 | return 1 13 | } 14 | -------------------------------------------------------------------------------- /fuzz/workdir/corpus/0379f1e9bc4a1c7fc02bd4872c66c73980064beb-1: -------------------------------------------------------------------------------- 1 | ҦİİҦİұ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/0449cf41cee451d4bc01593edffc33dbe4cc6ed8-5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/0449cf41cee451d4bc01593edffc33dbe4cc6ed8-5 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/057c9afef29f89efc31ce51a089e2ad07be862df: -------------------------------------------------------------------------------- 1 | İҦİ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/0939a9a26bc38f1987a4466571e5eee9118c362f: -------------------------------------------------------------------------------- 1 | İҦҦұ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/0a57cb53ba59c46fc4b692527a38a87c78d84028-6: -------------------------------------------------------------------------------- 1 | 28 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/0d651898c91e920fa9504f9237401a1df4a71230-5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/0d651898c91e920fa9504f9237401a1df4a71230-5 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/11ed49d6fd3446798f01865b44a88a19d110c310-5: -------------------------------------------------------------------------------- 1 | 14908747� -------------------------------------------------------------------------------- /fuzz/workdir/corpus/1634243a95c2478d2c760f5c30951dce97574987-3: -------------------------------------------------------------------------------- 1 | 8� -------------------------------------------------------------------------------- /fuzz/workdir/corpus/174d2deb68324c0b8bbd980bd86d06d9745e9b3c-5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/174d2deb68324c0b8bbd980bd86d06d9745e9b3c-5 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/197f19525eea560f3e2a93773fd4659da57af9ea-2: -------------------------------------------------------------------------------- 1 | B� -------------------------------------------------------------------------------- /fuzz/workdir/corpus/1abd5024b4ab05b023659daa1b920b9db1e13674-5: -------------------------------------------------------------------------------- 1 | 7Ʀ[+$ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/21f7d5621eeeadc6d44de46fddcd21f3b0904289-5: -------------------------------------------------------------------------------- 1 | 7Q^[A-ƨZ][^A-Z]+$ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/221d7c4034d32c379d10225c3b8e569f9b5a90bc-5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/221d7c4034d32c379d10225c3b8e569f9b5a90bc-5 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/2aae52a530b36be8974f6643bcb481f63ccbde1b-5: -------------------------------------------------------------------------------- 1 | 2149087 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/2b2c9df7e2a3027967cd9338759453b12cd7a3ff-1: -------------------------------------------------------------------------------- 1 | İ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/2e8a46cec8efb82bea0f6dd69e4447610420df19-3: -------------------------------------------------------------------------------- 1 | NwnsZS_S -------------------------------------------------------------------------------- /fuzz/workdir/corpus/3312b1dbba75726aa90a90e37c9a2cb501467e08-5: -------------------------------------------------------------------------------- 1 | 2148747� -------------------------------------------------------------------------------- /fuzz/workdir/corpus/3516d6010dac3e1d7581f415a3842226c7eb21ae-6: -------------------------------------------------------------------------------- 1 | 21747 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/366860784d965ee1640bf5bfd00f2c54315f93e5-1: -------------------------------------------------------------------------------- 1 | NwnUsZS0I_S -------------------------------------------------------------------------------- /fuzz/workdir/corpus/3702236b11bd1b301fd4dff3c3de331dfc151c29-3: -------------------------------------------------------------------------------- 1 | İİİ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/399e57b2fc5fbdc129e4b61e7818dadec3393886-6: -------------------------------------------------------------------------------- 1 | spatial8 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/3c52042a2628722948972dc55b7faa436e4bcbb6-4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/3c52042a2628722948972dc55b7faa436e4bcbb6-4 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/3d3d0067fcceec6b05977e38045960f452649d0e-1: -------------------------------------------------------------------------------- 1 | ZS0_S -------------------------------------------------------------------------------- /fuzz/workdir/corpus/3f7f6a85b994371d6d2504cadabcd60018e5c4aa-5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/3f7f6a85b994371d6d2504cadabcd60018e5c4aa-5 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/4709344ed6b1145c0172175c61403c4745035443-4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/4709344ed6b1145c0172175c61403c4745035443-4 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/47e3bb7dde4aabca19f5efc459e4423ceb7ab74c-2: -------------------------------------------------------------------------------- 1 | ҦܦҦ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/48f03a7b4c83fd21f52124bd5150ef0b2b3e8032-6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/48f03a7b4c83fd21f52124bd5150ef0b2b3e8032-6 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/492a7b0ae52963cb75a2e7a044ba49e58285621e-3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/492a7b0ae52963cb75a2e7a044ba49e58285621e-3 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/4f84679c1427b0081732ee473bef237010075356-5: -------------------------------------------------------------------------------- 1 | 7^ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/4fc780d545d57f9e2cedcff2259c2751c93a2002-5: -------------------------------------------------------------------------------- 1 | 214908 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/51edc2abfdba3a50e391323c4ba45559750ef5ef-6: -------------------------------------------------------------------------------- 1 | 149087 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/55e79155c1a348c03e4e4b71762819fe9efc6303-6: -------------------------------------------------------------------------------- 1 | 2198747 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/577869d54ae0beeaccd315f67777b801c53b9744-3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/577869d54ae0beeaccd315f67777b801c53b9744-3 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/596022f185b0bb13196bec3de9ab0100384c12fb-2: -------------------------------------------------------------------------------- 1 | B� -------------------------------------------------------------------------------- /fuzz/workdir/corpus/5a0a6bfc5fa088bec5cbaedfa71dc5d6f7f77b46: -------------------------------------------------------------------------------- 1 | İҦİұ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/5aefcaf6c8935ed7fc778b9b26905ac205ab8849-4: -------------------------------------------------------------------------------- 1 | 8 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/5be00875facc075657bde848eac3e9c63ec849bb-2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/5be00875facc075657bde848eac3e9c63ec849bb-2 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/62c8835e75525875f75f82944c9df50e11afb9cc: -------------------------------------------------------------------------------- 1 | Ɱ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/632cf624060aff03df13a547d60a8ad72b2b4b02-1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/632cf624060aff03df13a547d60a8ad72b2b4b02-1 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/64f907d2737089067ca4bfe099ef0a63938dd5de: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/64f907d2737089067ca4bfe099ef0a63938dd5de -------------------------------------------------------------------------------- /fuzz/workdir/corpus/6a33fdefa8afdbf1e6154912735b295717ce2eb6-1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/6a33fdefa8afdbf1e6154912735b295717ce2eb6-1 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/6d1c216c69100abd5c53d49ac1e35bee65d4ab70-3: -------------------------------------------------------------------------------- 1 | 5� -------------------------------------------------------------------------------- /fuzz/workdir/corpus/71c9db717578b9ee49a59e69375c16c0627dffef-3: -------------------------------------------------------------------------------- 1 | BB -------------------------------------------------------------------------------- /fuzz/workdir/corpus/7db1aa4b84213fad96badd59a197948bcc984195-4: -------------------------------------------------------------------------------- 1 | 214908747� -------------------------------------------------------------------------------- /fuzz/workdir/corpus/8312e3532bbc3c5b6273ec4af64dd554e0f5b836-4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/8312e3532bbc3c5b6273ec4af64dd554e0f5b836-4 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/83abf7ddc4394233286c9210087dabf03b19a153-3: -------------------------------------------------------------------------------- 1 | ƨ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/849cc30a6fb31a7978cd7e6f7d68cbcedd2dbfe7-5: -------------------------------------------------------------------------------- 1 | 2149G8747� -------------------------------------------------------------------------------- /fuzz/workdir/corpus/8750ec9ddfe293cd1dc39b4245c21c270f8f52b7-4: -------------------------------------------------------------------------------- 1 | �� -------------------------------------------------------------------------------- /fuzz/workdir/corpus/889046a524770e5e165728f24e54765eb18cbd08-1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/889046a524770e5e165728f24e54765eb18cbd08-1 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/8a0d5a57533dd35f721690857a5e64a65a7e294e-5: -------------------------------------------------------------------------------- 1 | 8747 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/8d96642d5dd2a537a5761c691f61af7551034bf0: -------------------------------------------------------------------------------- 1 | İҦҦ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/8ff92c267f61da0818b23b4dd4df0c6fd571eb98-5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/8ff92c267f61da0818b23b4dd4df0c6fd571eb98-5 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/91c1bb4961e8972dcd057c7162e6ffbf337422c3-6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/91c1bb4961e8972dcd057c7162e6ffbf337422c3-6 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/97140203053231c6afa57a7d3e42793e786b3c0d: -------------------------------------------------------------------------------- 1 | İİ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/99180e7785954b7e75337c7d68a878b16359ddef-5: -------------------------------------------------------------------------------- 1 | 21498747 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/9a0e5b94555df3dd524cf954b7cd098d04c0c5d2: -------------------------------------------------------------------------------- 1 | İ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/9f507d371a3beab3e95fb88db86c0ced13f96dca-1: -------------------------------------------------------------------------------- 1 | ҦĦҦ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/a3b2b4c9a873749376acd08f7e51381c4bd5d2ef-6: -------------------------------------------------------------------------------- 1 | 148747� -------------------------------------------------------------------------------- /fuzz/workdir/corpus/a51e63c32726ae35f64151509fabbc82c8fd73fa-4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/a51e63c32726ae35f64151509fabbc82c8fd73fa-4 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/a5a1deaea046a2a8fe3a5f54b6ac1e42c2d20443-4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/a5a1deaea046a2a8fe3a5f54b6ac1e42c2d20443-4 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/a60d1d9835e41888af15698172a415fbf9626445-3: -------------------------------------------------------------------------------- 1 | inity -------------------------------------------------------------------------------- /fuzz/workdir/corpus/a8c081c4053e6fd1e4620df28803f32308279b1d-5: -------------------------------------------------------------------------------- 1 | spatialj8� -------------------------------------------------------------------------------- /fuzz/workdir/corpus/ae4f281df5a5d0ff3cad6371f76d5c29b6d953ec-3: -------------------------------------------------------------------------------- 1 | B -------------------------------------------------------------------------------- /fuzz/workdir/corpus/afa8d4d4b28f4e13c30afc2c6d5982685614d4f9-4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/afa8d4d4b28f4e13c30afc2c6d5982685614d4f9-4 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/b28707e84c7f7e40c5f7ddc901c25054b66ee0d9-6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/b28707e84c7f7e40c5f7ddc901c25054b66ee0d9-6 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/b3af2d73132d1f991f8ef73eca1a8a98ad53f835-5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/b3af2d73132d1f991f8ef73eca1a8a98ad53f835-5 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/b608555928c295732b6ffe9e08386dbcdc59651c: -------------------------------------------------------------------------------- 1 | 0000000000000000000000000000000000000000000000000000000İ00000000000 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/be108be24a7b904db41b5eae4a2957df53e84df8-5: -------------------------------------------------------------------------------- 1 | 7Q^[]+$ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/c1f2cf4bd49167996a6f1464802fa3c0becff9c1-3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/c1f2cf4bd49167996a6f1464802fa3c0becff9c1-3 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/c9d123bd98167cb1093ba05f3873ae9c0e28e136-2: -------------------------------------------------------------------------------- 1 | NwnUsZS_S -------------------------------------------------------------------------------- /fuzz/workdir/corpus/cb8c7dec4b7dd839e050de86e4355f39e9ff446e-6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/cb8c7dec4b7dd839e050de86e4355f39e9ff446e-6 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/d28321f0aa0a4a985af875add48dab7dfaf46a1b-2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/d28321f0aa0a4a985af875add48dab7dfaf46a1b-2 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/d97af67d4a25957f1995000fc5515d402c0aa473: -------------------------------------------------------------------------------- 1 | İҦ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709-2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709-2 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/e1161af9333f4f87b04b5046261b26ec96df33a0-2: -------------------------------------------------------------------------------- 1 | Ҧİİİ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/e52e67036397fb8f6cc39ccfc635fcb7f01f7d38-5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/e52e67036397fb8f6cc39ccfc635fcb7f01f7d38-5 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/e8c0557385fa0e24f2abd06e83fb6b568aed8865-2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/e8c0557385fa0e24f2abd06e83fb6b568aed8865-2 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/e9e72a1bd62e3822b4345b1a027a930aca35d922-2: -------------------------------------------------------------------------------- 1 | Ʀ� -------------------------------------------------------------------------------- /fuzz/workdir/corpus/ebcd8d722dde05d862048deebfe5bc4cb48a5f6f-5: -------------------------------------------------------------------------------- 1 | 7][^A -------------------------------------------------------------------------------- /fuzz/workdir/corpus/ef814cd79d18b9bf1df32f2a5279e31406970ac4-4: -------------------------------------------------------------------------------- 1 | a9 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/f839a6d0ecaff3f478bcf3f51ce59da903d6a1d1: -------------------------------------------------------------------------------- 1 | ƦⱮ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/f9b258b5b82e1253631e6eeb4e2459f645dc0e4c-4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbutton23/zxcvbn-go/fa2cb2858354d539804173893953569804ed418e/fuzz/workdir/corpus/f9b258b5b82e1253631e6eeb4e2459f645dc0e4c-4 -------------------------------------------------------------------------------- /fuzz/workdir/corpus/fbc2ae73c4537afe3f7ad1457ec3685e97ba32a8-1: -------------------------------------------------------------------------------- 1 | Ʀ⨮ -------------------------------------------------------------------------------- /fuzz/workdir/corpus/fc1e27548a8e9191beb76c263c62f57fcc9b0855-3: -------------------------------------------------------------------------------- 1 | B -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/nbutton23/zxcvbn-go 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/davecgh/go-spew v1.1.0 7 | github.com/pmezard/go-difflib v1.0.0 8 | github.com/stretchr/testify v1.1.4 9 | ) 10 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 4 | github.com/stretchr/testify v1.1.4 h1:ToftOQTytwshuOSj6bDSolVUa3GINfJP/fg3OkkOzQQ= 5 | github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 6 | -------------------------------------------------------------------------------- /match/match.go: -------------------------------------------------------------------------------- 1 | package match 2 | 3 | //Matches is an alies for []Match used for sorting 4 | type Matches []Match 5 | 6 | func (s Matches) Len() int { 7 | return len(s) 8 | } 9 | func (s Matches) Swap(i, j int) { 10 | s[i], s[j] = s[j], s[i] 11 | } 12 | func (s Matches) Less(i, j int) bool { 13 | if s[i].I < s[j].I { 14 | return true 15 | } else if s[i].I == s[j].I { 16 | return s[i].J < s[j].J 17 | } else { 18 | return false 19 | } 20 | } 21 | 22 | // Match represents different matches 23 | type Match struct { 24 | Pattern string 25 | I, J int 26 | Token string 27 | DictionaryName string 28 | Entropy float64 29 | } 30 | 31 | //DateMatch is specifilly a match for type date 32 | type DateMatch struct { 33 | Pattern string 34 | I, J int 35 | Token string 36 | Separator string 37 | Day, Month, Year int64 38 | } 39 | 40 | //Matcher are a func and ID that can be used to match different passwords 41 | type Matcher struct { 42 | MatchingFunc func(password string) []Match 43 | ID string 44 | } 45 | -------------------------------------------------------------------------------- /matching/dateMatchers.go: -------------------------------------------------------------------------------- 1 | package matching 2 | 3 | import ( 4 | "regexp" 5 | "strconv" 6 | "strings" 7 | 8 | "github.com/nbutton23/zxcvbn-go/entropy" 9 | "github.com/nbutton23/zxcvbn-go/match" 10 | ) 11 | 12 | const ( 13 | dateSepMatcherName = "DATESEP" 14 | dateWithOutSepMatcherName = "DATEWITHOUT" 15 | ) 16 | 17 | var ( 18 | dateRxYearSuffix = regexp.MustCompile(`((\d{1,2})(\s|-|\/|\\|_|\.)(\d{1,2})(\s|-|\/|\\|_|\.)(19\d{2}|200\d|201\d|\d{2}))`) 19 | dateRxYearPrefix = regexp.MustCompile(`((19\d{2}|200\d|201\d|\d{2})(\s|-|/|\\|_|\.)(\d{1,2})(\s|-|/|\\|_|\.)(\d{1,2}))`) 20 | dateWithOutSepMatch = regexp.MustCompile(`\d{4,8}`) 21 | ) 22 | 23 | //FilterDateSepMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher 24 | func FilterDateSepMatcher(m match.Matcher) bool { 25 | return m.ID == dateSepMatcherName 26 | } 27 | 28 | //FilterDateWithoutSepMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher 29 | func FilterDateWithoutSepMatcher(m match.Matcher) bool { 30 | return m.ID == dateWithOutSepMatcherName 31 | } 32 | 33 | func checkDate(day, month, year int64) (bool, int64, int64, int64) { 34 | if (12 <= month && month <= 31) && day <= 12 { 35 | day, month = month, day 36 | } 37 | 38 | if day > 31 || month > 12 { 39 | return false, 0, 0, 0 40 | } 41 | 42 | if !((1900 <= year && year <= 2019) || (0 <= year && year <= 99)) { 43 | return false, 0, 0, 0 44 | } 45 | 46 | return true, day, month, year 47 | } 48 | 49 | func dateSepMatcher(password string) []match.Match { 50 | dateMatches := dateSepMatchHelper(password) 51 | 52 | var matches []match.Match 53 | for _, dateMatch := range dateMatches { 54 | match := match.Match{ 55 | I: dateMatch.I, 56 | J: dateMatch.J, 57 | Entropy: entropy.DateEntropy(dateMatch), 58 | DictionaryName: "date_match", 59 | Token: dateMatch.Token, 60 | } 61 | 62 | matches = append(matches, match) 63 | } 64 | 65 | return matches 66 | } 67 | func dateSepMatchHelper(password string) []match.DateMatch { 68 | 69 | var matches []match.DateMatch 70 | 71 | for _, v := range dateRxYearSuffix.FindAllString(password, len(password)) { 72 | splitV := dateRxYearSuffix.FindAllStringSubmatch(v, len(v)) 73 | i := strings.Index(password, v) 74 | j := i + len(v) 75 | day, _ := strconv.ParseInt(splitV[0][4], 10, 16) 76 | month, _ := strconv.ParseInt(splitV[0][2], 10, 16) 77 | year, _ := strconv.ParseInt(splitV[0][6], 10, 16) 78 | match := match.DateMatch{Day: day, Month: month, Year: year, Separator: splitV[0][5], I: i, J: j, Token: password[i:j]} 79 | matches = append(matches, match) 80 | } 81 | 82 | for _, v := range dateRxYearPrefix.FindAllString(password, len(password)) { 83 | splitV := dateRxYearPrefix.FindAllStringSubmatch(v, len(v)) 84 | i := strings.Index(password, v) 85 | j := i + len(v) 86 | day, _ := strconv.ParseInt(splitV[0][4], 10, 16) 87 | month, _ := strconv.ParseInt(splitV[0][6], 10, 16) 88 | year, _ := strconv.ParseInt(splitV[0][2], 10, 16) 89 | match := match.DateMatch{Day: day, Month: month, Year: year, Separator: splitV[0][5], I: i, J: j, Token: password[i:j]} 90 | matches = append(matches, match) 91 | } 92 | 93 | var out []match.DateMatch 94 | for _, match := range matches { 95 | if valid, day, month, year := checkDate(match.Day, match.Month, match.Year); valid { 96 | match.Pattern = "date" 97 | match.Day = day 98 | match.Month = month 99 | match.Year = year 100 | out = append(out, match) 101 | } 102 | } 103 | return out 104 | 105 | } 106 | 107 | type dateMatchCandidate struct { 108 | DayMonth string 109 | Year string 110 | I, J int 111 | } 112 | 113 | type dateMatchCandidateTwo struct { 114 | Day string 115 | Month string 116 | Year string 117 | I, J int 118 | } 119 | 120 | func dateWithoutSepMatch(password string) []match.Match { 121 | dateMatches := dateWithoutSepMatchHelper(password) 122 | 123 | var matches []match.Match 124 | for _, dateMatch := range dateMatches { 125 | match := match.Match{ 126 | I: dateMatch.I, 127 | J: dateMatch.J, 128 | Entropy: entropy.DateEntropy(dateMatch), 129 | DictionaryName: "date_match", 130 | Token: dateMatch.Token, 131 | } 132 | 133 | matches = append(matches, match) 134 | } 135 | 136 | return matches 137 | } 138 | 139 | //TODO Has issues with 6 digit dates 140 | func dateWithoutSepMatchHelper(password string) (matches []match.DateMatch) { 141 | for _, v := range dateWithOutSepMatch.FindAllString(password, len(password)) { 142 | i := strings.Index(password, v) 143 | j := i + len(v) 144 | length := len(v) 145 | lastIndex := length - 1 146 | var candidatesRoundOne []dateMatchCandidate 147 | 148 | if length <= 6 { 149 | //2-digit year prefix 150 | candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[2:], v[0:2], i, j)) 151 | 152 | //2-digityear suffix 153 | candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[0:lastIndex-2], v[lastIndex-2:], i, j)) 154 | } 155 | if length >= 6 { 156 | //4-digit year prefix 157 | candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[4:], v[0:4], i, j)) 158 | 159 | //4-digit year sufix 160 | candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[0:lastIndex-3], v[lastIndex-3:], i, j)) 161 | } 162 | 163 | var candidatesRoundTwo []dateMatchCandidateTwo 164 | for _, c := range candidatesRoundOne { 165 | if len(c.DayMonth) == 2 { 166 | candidatesRoundTwo = append(candidatesRoundTwo, buildDateMatchCandidateTwo(c.DayMonth[0:0], c.DayMonth[1:1], c.Year, c.I, c.J)) 167 | } else if len(c.DayMonth) == 3 { 168 | candidatesRoundTwo = append(candidatesRoundTwo, buildDateMatchCandidateTwo(c.DayMonth[0:2], c.DayMonth[2:2], c.Year, c.I, c.J)) 169 | candidatesRoundTwo = append(candidatesRoundTwo, buildDateMatchCandidateTwo(c.DayMonth[0:0], c.DayMonth[1:3], c.Year, c.I, c.J)) 170 | } else if len(c.DayMonth) == 4 { 171 | candidatesRoundTwo = append(candidatesRoundTwo, buildDateMatchCandidateTwo(c.DayMonth[0:2], c.DayMonth[2:4], c.Year, c.I, c.J)) 172 | } 173 | } 174 | 175 | for _, candidate := range candidatesRoundTwo { 176 | intDay, err := strconv.ParseInt(candidate.Day, 10, 16) 177 | if err != nil { 178 | continue 179 | } 180 | 181 | intMonth, err := strconv.ParseInt(candidate.Month, 10, 16) 182 | 183 | if err != nil { 184 | continue 185 | } 186 | 187 | intYear, err := strconv.ParseInt(candidate.Year, 10, 16) 188 | if err != nil { 189 | continue 190 | } 191 | 192 | if ok, _, _, _ := checkDate(intDay, intMonth, intYear); ok { 193 | matches = append(matches, match.DateMatch{Token: password, Pattern: "date", Day: intDay, Month: intMonth, Year: intYear, I: i, J: j}) 194 | } 195 | 196 | } 197 | } 198 | 199 | return matches 200 | } 201 | 202 | func buildDateMatchCandidate(dayMonth, year string, i, j int) dateMatchCandidate { 203 | return dateMatchCandidate{DayMonth: dayMonth, Year: year, I: i, J: j} 204 | } 205 | 206 | func buildDateMatchCandidateTwo(day, month string, year string, i, j int) dateMatchCandidateTwo { 207 | 208 | return dateMatchCandidateTwo{Day: day, Month: month, Year: year, I: i, J: j} 209 | } 210 | -------------------------------------------------------------------------------- /matching/dictionaryMatch.go: -------------------------------------------------------------------------------- 1 | package matching 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/nbutton23/zxcvbn-go/entropy" 7 | "github.com/nbutton23/zxcvbn-go/match" 8 | ) 9 | 10 | func buildDictMatcher(dictName string, rankedDict map[string]int) func(password string) []match.Match { 11 | return func(password string) []match.Match { 12 | matches := dictionaryMatch(password, dictName, rankedDict) 13 | for _, v := range matches { 14 | v.DictionaryName = dictName 15 | } 16 | return matches 17 | } 18 | 19 | } 20 | 21 | func dictionaryMatch(password string, dictionaryName string, rankedDict map[string]int) []match.Match { 22 | var results []match.Match 23 | pwLower := strings.ToLower(password) 24 | 25 | pwLowerRunes := []rune(pwLower) 26 | length := len(pwLowerRunes) 27 | 28 | for i := 0; i < length; i++ { 29 | for j := i; j < length; j++ { 30 | word := pwLowerRunes[i : j+1] 31 | if val, ok := rankedDict[string(word)]; ok { 32 | matchDic := match.Match{Pattern: "dictionary", 33 | DictionaryName: dictionaryName, 34 | I: i, 35 | J: j, 36 | Token: string([]rune(password)[i : j+1]), 37 | } 38 | matchDic.Entropy = entropy.DictionaryEntropy(matchDic, float64(val)) 39 | 40 | results = append(results, matchDic) 41 | } 42 | } 43 | } 44 | 45 | return results 46 | } 47 | 48 | func buildRankedDict(unrankedList []string) map[string]int { 49 | 50 | result := make(map[string]int) 51 | 52 | for i, v := range unrankedList { 53 | result[strings.ToLower(v)] = i + 1 54 | } 55 | 56 | return result 57 | } 58 | -------------------------------------------------------------------------------- /matching/leet.go: -------------------------------------------------------------------------------- 1 | package matching 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/nbutton23/zxcvbn-go/entropy" 7 | "github.com/nbutton23/zxcvbn-go/match" 8 | ) 9 | 10 | // L33TMatcherName id 11 | const L33TMatcherName = "l33t" 12 | 13 | //FilterL33tMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher 14 | func FilterL33tMatcher(m match.Matcher) bool { 15 | return m.ID == L33TMatcherName 16 | } 17 | 18 | func l33tMatch(password string) []match.Match { 19 | permutations := getPermutations(password) 20 | 21 | var matches []match.Match 22 | 23 | for _, permutation := range permutations { 24 | for _, mather := range dictionaryMatchers { 25 | matches = append(matches, mather.MatchingFunc(permutation)...) 26 | } 27 | } 28 | 29 | for _, match := range matches { 30 | match.Entropy += entropy.ExtraLeetEntropy(match, password) 31 | match.DictionaryName = match.DictionaryName + "_3117" 32 | } 33 | 34 | return matches 35 | } 36 | 37 | // This function creates a list of permutations based on a fixed table stored on data. The table 38 | // will be reduced in order to proceed in the function using only relevant values (see 39 | // relevantL33tSubtable). 40 | func getPermutations(password string) []string { 41 | substitutions := relevantL33tSubtable(password) 42 | permutations := getAllPermutationsOfLeetSubstitutions(password, substitutions) 43 | return permutations 44 | } 45 | 46 | // This function loads the table from data but only keep in memory the values that are present 47 | // inside the provided password. 48 | func relevantL33tSubtable(password string) map[string][]string { 49 | relevantSubs := make(map[string][]string) 50 | for key, values := range l33tTable.Graph { 51 | for _, value := range values { 52 | if strings.Contains(password, value) { 53 | relevantSubs[key] = append(relevantSubs[key], value) 54 | } 55 | } 56 | } 57 | 58 | return relevantSubs 59 | } 60 | 61 | // This function creates the list of permutations of a given password using the provided table as 62 | // reference for its operation. 63 | func getAllPermutationsOfLeetSubstitutions(password string, table map[string][]string) []string { 64 | result := []string{} 65 | 66 | // create a list of tables without conflicting keys/values (this happens for "|", "7" and "1") 67 | noConflictsTables := createListOfMapsWithoutConflicts(table) 68 | for _, noConflictsTable := range noConflictsTables { 69 | substitutionsMaps := createSubstitutionsMapsFromTable(noConflictsTable) 70 | for _, substitutionsMap := range substitutionsMaps { 71 | newValue := createWordForSubstitutionMap(password, substitutionsMap) 72 | if !stringSliceContainsValue(result, newValue) { 73 | result = append(result, newValue) 74 | } 75 | } 76 | } 77 | 78 | return result 79 | } 80 | 81 | // Create the possible list of maps removing the conflicts from it. As an example, the value "|" 82 | // may represent "i" and "l". For each representation of the conflicting value, a new map is 83 | // created. This may grow exponencialy according to the number of conflicts. The number of maps 84 | // returned by this function may be reduced if the relevantL33tSubtable function was called to 85 | // identify only relevant items. 86 | func createListOfMapsWithoutConflicts(table map[string][]string) []map[string][]string { 87 | // the resulting list starts with the provided table 88 | result := []map[string][]string{} 89 | result = append(result, table) 90 | 91 | // iterate over the list of conflicts in order to expand the maps for each one 92 | conflicts := retrieveConflictsListFromTable(table) 93 | for _, value := range conflicts { 94 | newMapList := []map[string][]string{} 95 | 96 | // for each conflict a new list of maps will be created for every already known map 97 | for _, currentMap := range result { 98 | newMaps := createDifferentMapsForLeetChar(currentMap, value) 99 | newMapList = append(newMapList, newMaps...) 100 | } 101 | 102 | result = newMapList 103 | } 104 | 105 | return result 106 | } 107 | 108 | // This function retrieves the list of values that appear for one or more keys. This is usefull to 109 | // know which l33t chars can represent more than one letter. 110 | func retrieveConflictsListFromTable(table map[string][]string) []string { 111 | result := []string{} 112 | foundValues := []string{} 113 | 114 | for _, values := range table { 115 | for _, value := range values { 116 | if stringSliceContainsValue(foundValues, value) { 117 | // only add on results if it was not identified as conflict before 118 | if !stringSliceContainsValue(result, value) { 119 | result = append(result, value) 120 | } 121 | } else { 122 | foundValues = append(foundValues, value) 123 | } 124 | } 125 | } 126 | 127 | return result 128 | } 129 | 130 | // This function aims to create different maps for a given char if this char represents a conflict. 131 | // If the specified char is not a conflit one, the same map will be returned. In scenarios which 132 | // the provided char can not be found on map, an empty list will be returned. This function was 133 | // designed to be used on conflicts situations. 134 | func createDifferentMapsForLeetChar(table map[string][]string, leetChar string) []map[string][]string { 135 | result := []map[string][]string{} 136 | 137 | keysWithSameValue := retrieveListOfKeysWithSpecificValueFromTable(table, leetChar) 138 | for _, key := range keysWithSameValue { 139 | newMap := copyMapRemovingSameValueFromOtherKeys(table, key, leetChar) 140 | result = append(result, newMap) 141 | } 142 | 143 | return result 144 | } 145 | 146 | // This function retrieves the list of keys that can be represented using the given value. 147 | func retrieveListOfKeysWithSpecificValueFromTable(table map[string][]string, valueToFind string) []string { 148 | result := []string{} 149 | 150 | for key, values := range table { 151 | for _, value := range values { 152 | if value == valueToFind && !stringSliceContainsValue(result, key) { 153 | result = append(result, key) 154 | } 155 | } 156 | } 157 | 158 | return result 159 | } 160 | 161 | // This function returns a lsit of substitution map from a given table. Each map in the result will 162 | // provide only one representation for each value. As an example, if the provided map contains the 163 | // values "@" and "4" in the possibilities to represent "a", two maps will be created where one 164 | // will contain "a" mapping to "@" and the other one will provide "a" mapping to "4". 165 | func createSubstitutionsMapsFromTable(table map[string][]string) []map[string]string { 166 | result := []map[string]string{{"": ""}} 167 | 168 | for key, values := range table { 169 | newResult := []map[string]string{} 170 | 171 | for _, mapInCurrentResult := range result { 172 | for _, value := range values { 173 | newMapForValue := copyMap(mapInCurrentResult) 174 | newMapForValue[key] = value 175 | newResult = append(newResult, newMapForValue) 176 | } 177 | } 178 | 179 | result = newResult 180 | } 181 | 182 | // verification to make sure that the slice was filled 183 | if len(result) == 1 && len(result[0]) == 1 && result[0][""] == "" { 184 | return []map[string]string{} 185 | } 186 | 187 | return result 188 | } 189 | 190 | // This function replaces the values provided on substitution map over the provided word. 191 | func createWordForSubstitutionMap(word string, substitutionMap map[string]string) string { 192 | result := word 193 | for key, value := range substitutionMap { 194 | result = strings.Replace(result, value, key, -1) 195 | } 196 | 197 | return result 198 | } 199 | 200 | func stringSliceContainsValue(slice []string, value string) bool { 201 | for _, valueInSlice := range slice { 202 | if valueInSlice == value { 203 | return true 204 | } 205 | } 206 | 207 | return false 208 | } 209 | 210 | func copyMap(table map[string]string) map[string]string { 211 | result := make(map[string]string) 212 | 213 | for key, value := range table { 214 | result[key] = value 215 | } 216 | 217 | return result 218 | } 219 | 220 | // This function creates a new map based on the one provided but excluding possible representations 221 | // of the same value on other keys. 222 | func copyMapRemovingSameValueFromOtherKeys(table map[string][]string, keyToFix string, valueToFix string) map[string][]string { 223 | result := make(map[string][]string) 224 | 225 | for key, values := range table { 226 | for _, value := range values { 227 | if !(value == valueToFix && key != keyToFix) { 228 | result[key] = append(result[key], value) 229 | } 230 | } 231 | } 232 | 233 | return result 234 | } 235 | -------------------------------------------------------------------------------- /matching/leet_test.go: -------------------------------------------------------------------------------- 1 | package matching 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "sort" 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func TestLeetCanCreateSubstitutionMapsFromTable(t *testing.T) { 13 | table01 := map[string][]string{ 14 | "a": []string{"@"}, 15 | "b": []string{"8"}, 16 | "g": []string{"6"}, 17 | } 18 | 19 | table02 := map[string][]string{ 20 | "a": []string{"@", "4"}, 21 | "b": []string{"8"}, 22 | } 23 | 24 | table03 := map[string][]string{ 25 | "a": []string{"@", "4"}, 26 | "b": []string{"8"}, 27 | "g": []string{"6", "9"}, 28 | } 29 | 30 | table04 := map[string][]string{ 31 | "a": []string{"@", "4"}, 32 | "b": []string{"8"}, 33 | "g": []string{"6", "9"}, 34 | "i": []string{"1", "!", "|"}, 35 | } 36 | 37 | table05 := map[string][]string{ 38 | "a": []string{"@", "4"}, 39 | "b": []string{"8"}, 40 | "g": []string{"6", "9"}, 41 | "l": []string{"!", "1", "|", "7"}, 42 | } 43 | 44 | tests := []struct { 45 | name string 46 | table map[string][]string 47 | expectedListSize int 48 | }{ 49 | {"Empty map generates an empty substitution map", map[string][]string{}, 0}, 50 | {"Table with single values for every key returns only one substititution map", table01, 1}, 51 | {"Table with two values on one key returns two substititution maps", table02, 2}, 52 | {"Table with two values on two keys returns four substititution maps", table03, 4}, 53 | {"Table should generate a substititution map with exponential variation according to table values (2*2*3 = 12)", table04, 12}, 54 | {"Table should generate a substititution map with exponential variation according to table values (2*2*4 = 16)", table05, 16}, 55 | } 56 | 57 | for _, test := range tests { 58 | t.Run(test.name, func(t *testing.T) { 59 | result := createSubstitutionsMapsFromTable(test.table) 60 | assert.Equal(t, test.expectedListSize, len(result)) 61 | }) 62 | } 63 | } 64 | 65 | func TestSubstitutionWorksProperly(t *testing.T) { 66 | tests := []struct { 67 | name string 68 | table map[string]string 69 | word string 70 | expectedWord string 71 | }{ 72 | {"Word generated properly using substitution map", map[string]string{}, "password", "password"}, 73 | {"Word generated properly using substitution map", map[string]string{}, "p@ssword", "p@ssword"}, 74 | {"Word generated properly using substitution map", map[string]string{}, "p@$$w0rd", "p@$$w0rd"}, 75 | {"Word generated properly using substitution map", map[string]string{}, "p@$$w0rD", "p@$$w0rD"}, 76 | {"Word generated properly using substitution map", map[string]string{"a": "4"}, "p@ssword", "p@ssword"}, 77 | {"Word generated properly using substitution map", map[string]string{"a": "@"}, "p@ssword", "password"}, 78 | {"Word generated properly using substitution map", map[string]string{"a": "@"}, "p@$$word", "pa$$word"}, 79 | {"Word generated properly using substitution map", map[string]string{"a": "@", "s": "$"}, "p@$$word", "password"}, 80 | {"Word generated properly using substitution map", map[string]string{"a": "@", "s": "$", "o": "0"}, "p@$$w0rd", "password"}, 81 | {"Word generated properly using substitution map", map[string]string{"a": "@", "s": "$", "o": "0"}, "p@$$w0rD", "passworD"}, 82 | {"Word generated properly using substitution map", map[string]string{"i": "|"}, "|1|1|1|1|1|1|1|1|", "i1i1i1i1i1i1i1i1i"}, 83 | {"Word generated properly using substitution map", map[string]string{"i": "1"}, "|1|1|1|1|1|1|1|1|", "|i|i|i|i|i|i|i|i|"}, 84 | {"Word generated properly using substitution map", map[string]string{"i": "|", "l": "1"}, "|1|1|1|1|1|1|1|1|", "ilililililililili"}, 85 | } 86 | 87 | for _, test := range tests { 88 | t.Run(test.name, func(t *testing.T) { 89 | assert.Equal(t, test.expectedWord, createWordForSubstitutionMap(test.word, test.table)) 90 | }) 91 | } 92 | } 93 | 94 | func TestLeetCanListConflictsOnTable(t *testing.T) { 95 | mapWithoutConflicts := map[string][]string{ 96 | "a": []string{"@", "4"}, 97 | "b": []string{"8"}, 98 | "e": []string{"3"}, 99 | "g": []string{"6", "9"}, 100 | } 101 | 102 | mapWithOneConflictInTwoKeys := map[string][]string{ 103 | "a": []string{"@", "4"}, 104 | "b": []string{"8"}, 105 | "g": []string{"6", "9"}, 106 | "i": []string{"1", "!"}, 107 | "l": []string{"1", "|"}, 108 | } 109 | 110 | mapWithTwoConflicts := map[string][]string{ 111 | "a": []string{"@", "4"}, 112 | "b": []string{"8"}, 113 | "g": []string{"6", "9"}, 114 | "i": []string{"1", "!", "|"}, 115 | "l": []string{"1", "|", "7"}, 116 | } 117 | 118 | mapWithOneConflictInThreeKeys := map[string][]string{ 119 | "a": []string{"@", "4"}, 120 | "b": []string{"8"}, 121 | "g": []string{"6", "9"}, 122 | "i": []string{"1", "!"}, 123 | "l": []string{"1", "|", "7"}, 124 | "t": []string{"+", "1"}, 125 | } 126 | 127 | regularMap := map[string][]string{ 128 | "a": []string{"@", "4"}, 129 | "b": []string{"8"}, 130 | "c": []string{"(", "{", "[", "<"}, 131 | "e": []string{"3"}, 132 | "g": []string{"6", "9"}, 133 | "i": []string{"1", "!", "|"}, 134 | "l": []string{"1", "|", "7"}, 135 | "o": []string{"0"}, 136 | "s": []string{"$", "5"}, 137 | "t": []string{"+", "7"}, 138 | "x": []string{"%"}, 139 | "z": []string{"2"}, 140 | } 141 | 142 | tests := []struct { 143 | name string 144 | table map[string][]string 145 | expectedList []string 146 | }{ 147 | {"Empty map generates an empty conflicts list", map[string][]string{}, []string{}}, 148 | {"Map without conflicts generates an empty conflicts list", mapWithoutConflicts, []string{}}, 149 | {"Map with one conflict generates the conflicts list properly", mapWithOneConflictInTwoKeys, []string{"1"}}, 150 | {"Map with two conflicts generates the conflicts list properly", mapWithTwoConflicts, []string{"1", "|"}}, 151 | {"Map with one conflict generates the conflicts list properly even for three keys", mapWithOneConflictInThreeKeys, []string{"1"}}, 152 | {"Regular map generates the conflicts list properly", regularMap, []string{"1", "|", "7"}}, 153 | } 154 | 155 | for _, test := range tests { 156 | t.Run(test.name, func(t *testing.T) { 157 | result := retrieveConflictsListFromTable(test.table) 158 | 159 | // these sorts are necessary to make sure that the comparison will happen as expected 160 | sort.Strings(test.expectedList) 161 | sort.Strings(result) 162 | 163 | assert.Equal(t, test.expectedList, result) 164 | }) 165 | } 166 | } 167 | 168 | func TestLeetCanListKeysWithSpecificValueOnTable(t *testing.T) { 169 | mapWithoutConflicts := map[string][]string{ 170 | "a": []string{"@", "4"}, 171 | "b": []string{"8"}, 172 | "e": []string{"3"}, 173 | "g": []string{"6", "9"}, 174 | } 175 | 176 | mapWithOneConflictInTwoKeys := map[string][]string{ 177 | "a": []string{"@", "4"}, 178 | "b": []string{"8"}, 179 | "g": []string{"6", "9"}, 180 | "i": []string{"1", "!"}, 181 | "l": []string{"1", "|"}, 182 | } 183 | 184 | mapWithTwoConflicts := map[string][]string{ 185 | "a": []string{"@", "4"}, 186 | "b": []string{"8"}, 187 | "g": []string{"6", "9"}, 188 | "i": []string{"1", "!", "|"}, 189 | "l": []string{"1", "|", "7"}, 190 | } 191 | 192 | mapWithOneConflictInThreeKeys := map[string][]string{ 193 | "a": []string{"@", "4"}, 194 | "b": []string{"8"}, 195 | "g": []string{"6", "9"}, 196 | "i": []string{"1", "!"}, 197 | "l": []string{"1", "|", "7"}, 198 | "t": []string{"+", "1"}, 199 | } 200 | 201 | regularMap := map[string][]string{ 202 | "a": []string{"@", "4"}, 203 | "b": []string{"8"}, 204 | "c": []string{"(", "{", "[", "<"}, 205 | "e": []string{"3"}, 206 | "g": []string{"6", "9"}, 207 | "i": []string{"1", "!", "|"}, 208 | "l": []string{"1", "|", "7"}, 209 | "o": []string{"0"}, 210 | "s": []string{"$", "5"}, 211 | "t": []string{"+", "7"}, 212 | "x": []string{"%"}, 213 | "z": []string{"2"}, 214 | } 215 | 216 | tests := []struct { 217 | name string 218 | table map[string][]string 219 | valueToFind string 220 | expectedList []string 221 | }{ 222 | {"Empty map generates an empty list", map[string][]string{}, "@", []string{}}, 223 | {"Map without conflicts returns only one representation for leet char", mapWithoutConflicts, "@", []string{"a"}}, 224 | {"Map without conflicts returns no representation for unknown leet char", mapWithoutConflicts, "&", []string{}}, 225 | {"Map with one conflict generates the list properly for conflicting value", mapWithOneConflictInTwoKeys, "1", []string{"i", "l"}}, 226 | {"Map with one conflict generates the list properly for non conflicting value", mapWithOneConflictInTwoKeys, "|", []string{"l"}}, 227 | {"Map with two conflicts generates the list properly for conflicting value (1)", mapWithTwoConflicts, "1", []string{"i", "l"}}, 228 | {"Map with two conflicts generates the list properly for conflicting value (|)", mapWithTwoConflicts, "|", []string{"i", "l"}}, 229 | {"Map with two conflicts generates the list properly for non conflicting value in conflicting key (i)", mapWithTwoConflicts, "!", []string{"i"}}, 230 | {"Map with two conflicts generates the list properly for non conflicting value in conflicting key (l)", mapWithTwoConflicts, "7", []string{"l"}}, 231 | {"Map with one conflict generates the list properly even for three keys", mapWithOneConflictInThreeKeys, "1", []string{"i", "l", "t"}}, 232 | {"Regular map generates the list properly for conflicting value (|)", regularMap, "|", []string{"i", "l"}}, 233 | {"Regular map generates the list properly for conflicting value (7)", regularMap, "7", []string{"l", "t"}}, 234 | {"Regular map generates the list properly for non conflicting value", regularMap, "@", []string{"a"}}, 235 | {"Regular map generates the list properly for unknown value", regularMap, "&", []string{}}, 236 | {"Regular map generates the list properly for empty value", regularMap, "", []string{}}, 237 | } 238 | 239 | for _, test := range tests { 240 | t.Run(test.name, func(t *testing.T) { 241 | result := retrieveListOfKeysWithSpecificValueFromTable(test.table, test.valueToFind) 242 | 243 | // these sorts are necessary to make sure that the comparison will happen as expected 244 | sort.Strings(test.expectedList) 245 | sort.Strings(result) 246 | 247 | assert.Equal(t, test.expectedList, result) 248 | }) 249 | } 250 | } 251 | 252 | func TestLeetCanCreateDifferentTablesForConflictingChar(t *testing.T) { 253 | mapWithoutConflicts := map[string][]string{ 254 | "a": []string{"@", "4"}, 255 | "b": []string{"8"}, 256 | "e": []string{"3"}, 257 | "g": []string{"6", "9"}, 258 | } 259 | 260 | mapWithTwoConflicts := map[string][]string{ 261 | "a": []string{"@", "4"}, 262 | "b": []string{"8"}, 263 | "g": []string{"6", "9"}, 264 | "i": []string{"1", "!", "|"}, 265 | "l": []string{"1", "|", "7"}, 266 | } 267 | 268 | mapWithOneConflictInThreeKeys := map[string][]string{ 269 | "a": []string{"@", "4"}, 270 | "b": []string{"8"}, 271 | "g": []string{"6", "9"}, 272 | "i": []string{"1", "!"}, 273 | "l": []string{"1", "|", "7"}, 274 | "t": []string{"+", "1"}, 275 | } 276 | 277 | tests := []struct { 278 | name string 279 | table map[string][]string 280 | leetChar string 281 | expectedListOfMapsSize int 282 | }{ 283 | {"Empty map must return no map on result", map[string][]string{}, "", 0}, 284 | {"Map without conflicts generates the same map on result", mapWithoutConflicts, "4", 1}, 285 | {"Map without conflicts generates no map on result for unknown char", mapWithoutConflicts, "&", 0}, 286 | {"Map with two conflicts generates two maps using conflicting char", mapWithTwoConflicts, "|", 2}, 287 | {"Map with two conflicts generates the same map using non conflicting char", mapWithTwoConflicts, "8", 1}, 288 | {"Map with two conflicts generates no map using not existing char", mapWithTwoConflicts, "2", 0}, 289 | {"Map with one conflict in three keys generates three maps", mapWithOneConflictInThreeKeys, "1", 3}, 290 | } 291 | 292 | for _, test := range tests { 293 | t.Run(test.name, func(t *testing.T) { 294 | assert.Equal(t, test.expectedListOfMapsSize, len(createDifferentMapsForLeetChar(test.table, test.leetChar))) 295 | }) 296 | } 297 | } 298 | 299 | func TestLeetCanCreateTablesWithoutConflict(t *testing.T) { 300 | mapWithoutConflicts := map[string][]string{ 301 | "a": []string{"@", "4"}, 302 | "b": []string{"8"}, 303 | "e": []string{"3"}, 304 | "g": []string{"6", "9"}, 305 | } 306 | 307 | mapWithTwoConflicts := map[string][]string{ 308 | "a": []string{"@", "4"}, 309 | "b": []string{"8"}, 310 | "g": []string{"6", "9"}, 311 | "i": []string{"1", "!", "|"}, 312 | "l": []string{"1", "|", "7"}, 313 | } 314 | 315 | mapWithOneConflictInThreeKeys := map[string][]string{ 316 | "a": []string{"@", "4"}, 317 | "b": []string{"8"}, 318 | "g": []string{"6", "9"}, 319 | "i": []string{"1", "!"}, 320 | "l": []string{"1", "|", "7"}, 321 | "t": []string{"+", "1"}, 322 | } 323 | 324 | mapThatGeneratesTwelveOtherMaps := map[string][]string{ 325 | "a": []string{"@", "4", "9"}, 326 | "b": []string{"8"}, 327 | "g": []string{"6", "9"}, 328 | "i": []string{"1", "!"}, 329 | "l": []string{"1", "|", "7"}, 330 | "t": []string{"+", "1", "7"}, 331 | } 332 | 333 | tests := []struct { 334 | name string 335 | table map[string][]string 336 | expectedListOfMapsSize int 337 | }{ 338 | {"Empty map must return only the same map on result", map[string][]string{}, 1}, 339 | {"Map without conflicts generates the same map on result", mapWithoutConflicts, 1}, 340 | {"Map with two conflicts generates four maps", mapWithTwoConflicts, 4}, 341 | {"Map with one conflict in three keys generates three maps", mapWithOneConflictInThreeKeys, 3}, 342 | {"An specific map should generate twelve other maps", mapThatGeneratesTwelveOtherMaps, 12}, 343 | } 344 | 345 | for _, test := range tests { 346 | t.Run(test.name, func(t *testing.T) { 347 | assert.Equal(t, test.expectedListOfMapsSize, len(createListOfMapsWithoutConflicts(test.table))) 348 | }) 349 | } 350 | } 351 | 352 | func TestStringSliceContainsValueFunction(t *testing.T) { 353 | tests := []struct { 354 | name string 355 | slice []string 356 | value string 357 | expectedResult bool 358 | }{ 359 | {"Empty slice contains no value", []string{}, "a", false}, 360 | {"Empty slice contains no value, even if it is empty string", []string{}, "", false}, 361 | {"Empty string is a valid value", []string{""}, "", true}, 362 | {"Empty string is a valid value among others", []string{"0", "1", "", "a", "b"}, "", true}, 363 | {"Empty string can not be found among others if it is not on list", []string{"0", "1", "a", "b"}, "", false}, 364 | {"Slice with one value contains the stored value", []string{"a"}, "a", true}, 365 | {"Slice with one value does not contain wrong value", []string{"a"}, "b", false}, 366 | {"Slice with many items contains the stored value", []string{"a", "b", "c", "d", "0"}, "c", true}, 367 | {"Slice with many items does not contain wrong value", []string{"a", "b", "c", "d", "0"}, "2", false}, 368 | {"Slice with many items does not contain a value that looks like one that is stored", []string{"a", "b", "c", "d", "0"}, "C", false}, 369 | {"Slice with many items does not contain a value that includes an space character", []string{"a", "b", "c", "d", "0"}, "c ", false}, 370 | } 371 | 372 | for _, test := range tests { 373 | t.Run(test.name, func(t *testing.T) { 374 | assert.Equal(t, test.expectedResult, stringSliceContainsValue(test.slice, test.value)) 375 | }) 376 | } 377 | } 378 | 379 | func TestCopyMapRemovingSameValueFromOtherKeysFunction(t *testing.T) { 380 | map01 := map[string][]string{ 381 | "a": []string{"@", "4"}, 382 | "b": []string{"8"}, 383 | "g": []string{"6", "9"}, 384 | "i": []string{"1", "!"}, 385 | "l": []string{"1", "|"}, 386 | } 387 | 388 | expectedMap01 := map[string][]string{ 389 | "a": []string{"@", "4"}, 390 | "b": []string{"8"}, 391 | "g": []string{"6", "9"}, 392 | "i": []string{"1", "!"}, 393 | "l": []string{"|"}, 394 | } 395 | 396 | map02 := map[string][]string{ 397 | "a": []string{"@", "4"}, 398 | "b": []string{"8"}, 399 | "g": []string{"6", "9"}, 400 | "i": []string{"1", "!", "|"}, 401 | "l": []string{"1", "|", "7"}, 402 | } 403 | 404 | expectedMap02 := map[string][]string{ 405 | "a": []string{"@", "4"}, 406 | "b": []string{"8"}, 407 | "g": []string{"6", "9"}, 408 | "i": []string{"1", "!"}, 409 | "l": []string{"1", "|", "7"}, 410 | } 411 | 412 | map03 := map[string][]string{ 413 | "a": []string{"@", "4"}, 414 | "b": []string{"8"}, 415 | "g": []string{"6", "9"}, 416 | "i": []string{"1", "!"}, 417 | "l": []string{"1", "|", "7"}, 418 | "t": []string{"+", "1"}, 419 | } 420 | 421 | expectedMap03 := map[string][]string{ 422 | "a": []string{"@", "4"}, 423 | "b": []string{"8"}, 424 | "g": []string{"6", "9"}, 425 | "i": []string{"!"}, 426 | "l": []string{"1", "|", "7"}, 427 | "t": []string{"+"}, 428 | } 429 | 430 | tests := []struct { 431 | name string 432 | table map[string][]string 433 | keyToFix string 434 | valueToFix string 435 | expectedTable map[string][]string 436 | }{ 437 | {"Copy of map removing same value from other keys - test 01", map01, "i", "1", expectedMap01}, 438 | {"Copy of map removing same value from other keys - test 02", map02, "l", "|", expectedMap02}, 439 | {"Copy of map removing same value from other keys - test 03", map03, "l", "1", expectedMap03}, 440 | } 441 | 442 | for _, test := range tests { 443 | t.Run(test.name, func(t *testing.T) { 444 | assert.Equal(t, test.expectedTable, copyMapRemovingSameValueFromOtherKeys(test.table, test.keyToFix, test.valueToFix)) 445 | }) 446 | } 447 | } 448 | 449 | func TestLeetSubTable(t *testing.T) { 450 | subs := relevantL33tSubtable("password") 451 | assert.Len(t, subs, 0, "password should produce no leet subs") 452 | 453 | subs = relevantL33tSubtable("p4ssw0rd") 454 | assert.Len(t, subs, 2, "p4ssw0rd should produce 2 subs") 455 | 456 | subs = relevantL33tSubtable("1eet") 457 | assert.Len(t, subs, 2, "1eet should produce 2 subs") 458 | assert.Equal(t, subs["i"][0], "1") 459 | assert.Equal(t, subs["l"][0], "1") 460 | 461 | subs = relevantL33tSubtable("4pple@pple") 462 | assert.Len(t, subs, 1, "4pple@pple should produce 1 subs") 463 | assert.Len(t, subs["a"], 2) 464 | } 465 | 466 | func TestPermutationsOfLeetSubstitution(t *testing.T) { 467 | tests := []struct { 468 | name string 469 | word string 470 | expectedWords []string 471 | }{ 472 | {"Permutation returns the expected list", "1337", []string{"1eel", "ieel", "ieet", "lee7", "leet"}}, 473 | {"Permutation returns the expected list", "l33t", []string{"leet"}}, 474 | {"Permutation returns the expected list", "password", []string{}}, 475 | {"Permutation returns the expected list", "p@ssword", []string{"password"}}, 476 | {"Permutation returns the expected list", "p@$$word", []string{"password"}}, 477 | {"Permutation returns the expected list", "p@$$w0rd", []string{"password"}}, 478 | {"Permutation returns the expected list", "p@4a$$w0rd", []string{"pa4assword", "p@aassword"}}, 479 | {"Permutation returns the expected list", "|1|1|1|", []string{"i1i1i1i", "l1l1l1l", "|i|i|i|", "|l|l|l|", "lililil", "ililili"}}, 480 | {"Permutation returns the expected list", "|1|1|@", []string{"i1i1ia", "l1l1la", "|i|i|a", "|l|l|a", "lilila", "ililia"}}, 481 | {"Permutation returns the expected list", "1|1|@7", []string{"1i1ial", "1i1iat", "1l1la7", "1l1lat", "1|1|al", "ilila7", "ililat", "i|i|al", "i|i|at", "lilia7", "liliat", "l|l|a7", "l|l|at"}}, 482 | {"Permutation returns the expected list", "1|1|@74", []string{"1i1ial4", "1i1iat4", "1l1la74", "1l1lat4", "1|1|al4", "ilila74", "ililat4", "i|i|al4", "i|i|at4", "lilia74", "liliat4", "l|l|a74", "l|l|at4", "1i1i@la", "1i1i@ta", "1l1l@7a", "1l1l@ta", "1|1|@la", "ilil@7a", "ilil@ta", "i|i|@la", "i|i|@ta", "lili@7a", "lili@ta", "l|l|@7a", "l|l|@ta"}}, 483 | } 484 | 485 | for _, test := range tests { 486 | t.Run(test.name, func(t *testing.T) { 487 | result := getPermutations(test.word) 488 | 489 | // these sorts are necessary to make sure that the comparison will happen as expected 490 | sort.Strings(result) 491 | sort.Strings(test.expectedWords) 492 | 493 | assert.Equal(t, test.expectedWords, result) 494 | }) 495 | } 496 | } 497 | 498 | func TestPermutationsLenOfLeetSubstitutions(t *testing.T) { 499 | // scenarios with just one possible substitution must return only one human readable value 500 | checkPermutationsLen(t, "p4ssw0rd", 1) 501 | checkPermutationsLen(t, "p4$sw0rd", 1) 502 | checkPermutationsLen(t, "p4$$w0rd", 1) 503 | checkPermutationsLen(t, "p@$$w0rd", 1) 504 | checkPermutationsLen(t, "l33t", 1) 505 | checkPermutationsLen(t, "p@$$w0rdp@$$w0rdp@$$w0rdp@$$w0rdp@$$w0rdp@$$w0rdp@$$w0rdp@$$w0rdp@$$w0rdp@$$w0rd", 1) 506 | 507 | // number of variations are exponential if has more than one representation for same char 508 | checkPermutationsLen(t, "@", 1) 509 | checkPermutationsLen(t, "@4", 2) 510 | checkPermutationsLen(t, "@4(", 2) 511 | checkPermutationsLen(t, "@4({", 2*2) 512 | checkPermutationsLen(t, "@4({[", 2*3) 513 | checkPermutationsLen(t, "@4({[6", 2*3) 514 | checkPermutationsLen(t, "@4({[69", 2*3*2) 515 | 516 | // scenarios with no substitutions must return no result 517 | checkPermutationsLen(t, "test some good pass with this", 0) 518 | checkPermutationsLen(t, "no substitution should be made here", 0) 519 | checkPermutationsLen(t, "no substitution even with > . , ] } º # &", 0) 520 | checkPermutationsLen(t, "no SUBSTITUTION even with > . , ] } º # &", 0) 521 | 522 | // special characters without conflic should be replaced only by one human readable character 523 | checkPermutationsLen(t, "@@@@@@333333+++++(((((", 1) 524 | checkPermutationsLen(t, "@@@@@@333333+++++{{{{{", 1) 525 | checkPermutationsLen(t, "@@@@@@333333+++++[[[[[", 1) 526 | 527 | // if there is a conflicting character, consider all available options (but only one per time) 528 | checkPermutationsLen(t, "this_is_[[{{((hanging", 3) 529 | checkPermutationsLen(t, "p@$$w0rd 4", 2) 530 | checkPermutationsLen(t, "1337", 5) 531 | checkPermutationsLen(t, "7331", 5) 532 | checkPermutationsLen(t, "%6|a(+|<91%{s91![go0li0soe||", 56) // it was an out of memory scenarion 533 | checkPermutationsLen(t, "|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|", 6) // it was an out of memory scenarion 534 | checkPermutationsLen(t, "7|1!7|1!7|1!7|1!7|1!69", 28) // it was an out of memory scenarion 535 | checkPermutationsLen(t, "4@8({[<3691!|1|70$5+7%24@8({[<36", 544) // the worst scenario 536 | checkPermutationsLen(t, "4@8({[<3691!|1|70$5+7%24@8({[<364@8({[<3691!|1|70$5+7%24@8({[<364@8({[<3691!|1|70$5+7%24@8({[<36", 544) // the worst scenario x3 times 537 | checkPermutationsLen(t, "p4$$w0rd @1!|", 14) 538 | checkPermutationsLen(t, "m&u]z^ou;\\!0o7t*x}uo)[s%kb618h#'gks|z\\!l3%8:z>pcq=!5w%\"%gs~@]5as`g&.'\\z4/\\`.nz$>yck.!%twu{})|%x8)$6\"", 112) 539 | } 540 | 541 | func checkPermutationsLen(t *testing.T, password string, permutationsLen int) { 542 | permutations := getPermutations(password) 543 | assert.Len(t, permutations, permutationsLen) 544 | } 545 | 546 | func TestLeet(t *testing.T) { 547 | password := "1337" 548 | matches := l33tMatch(password) 549 | bytes, _ := json.Marshal(matches) 550 | fmt.Println(string(bytes)) 551 | fmt.Println(matches[0].J) 552 | } 553 | -------------------------------------------------------------------------------- /matching/matching.go: -------------------------------------------------------------------------------- 1 | package matching 2 | 3 | import ( 4 | "sort" 5 | 6 | "github.com/nbutton23/zxcvbn-go/adjacency" 7 | "github.com/nbutton23/zxcvbn-go/frequency" 8 | "github.com/nbutton23/zxcvbn-go/match" 9 | ) 10 | 11 | var ( 12 | dictionaryMatchers []match.Matcher 13 | matchers []match.Matcher 14 | adjacencyGraphs []adjacency.Graph 15 | l33tTable adjacency.Graph 16 | 17 | sequences map[string]string 18 | ) 19 | 20 | func init() { 21 | loadFrequencyList() 22 | } 23 | 24 | // Omnimatch runs all matchers against the password 25 | func Omnimatch(password string, userInputs []string, filters ...func(match.Matcher) bool) (matches []match.Match) { 26 | 27 | //Can I run into the issue where nil is not equal to nil? 28 | if dictionaryMatchers == nil || adjacencyGraphs == nil { 29 | loadFrequencyList() 30 | } 31 | 32 | if userInputs != nil { 33 | userInputMatcher := buildDictMatcher("user_inputs", buildRankedDict(userInputs)) 34 | matches = userInputMatcher(password) 35 | } 36 | 37 | for _, matcher := range matchers { 38 | shouldBeFiltered := false 39 | for i := range filters { 40 | if filters[i](matcher) { 41 | shouldBeFiltered = true 42 | break 43 | } 44 | } 45 | if !shouldBeFiltered { 46 | matches = append(matches, matcher.MatchingFunc(password)...) 47 | } 48 | } 49 | sort.Sort(match.Matches(matches)) 50 | return matches 51 | } 52 | 53 | func loadFrequencyList() { 54 | 55 | for n, list := range frequency.Lists { 56 | dictionaryMatchers = append(dictionaryMatchers, match.Matcher{MatchingFunc: buildDictMatcher(n, buildRankedDict(list.List)), ID: n}) 57 | } 58 | 59 | l33tTable = adjacency.GraphMap["l33t"] 60 | 61 | adjacencyGraphs = append(adjacencyGraphs, adjacency.GraphMap["qwerty"]) 62 | adjacencyGraphs = append(adjacencyGraphs, adjacency.GraphMap["dvorak"]) 63 | adjacencyGraphs = append(adjacencyGraphs, adjacency.GraphMap["keypad"]) 64 | adjacencyGraphs = append(adjacencyGraphs, adjacency.GraphMap["macKeypad"]) 65 | 66 | //l33tFilePath, _ := filepath.Abs("adjacency/L33t.json") 67 | //L33T_TABLE = adjacency.GetAdjancencyGraphFromFile(l33tFilePath, "l33t") 68 | 69 | sequences = make(map[string]string) 70 | sequences["lower"] = "abcdefghijklmnopqrstuvwxyz" 71 | sequences["upper"] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 72 | sequences["digits"] = "0123456789" 73 | 74 | matchers = append(matchers, dictionaryMatchers...) 75 | matchers = append(matchers, match.Matcher{MatchingFunc: spatialMatch, ID: spatialMatcherName}) 76 | matchers = append(matchers, match.Matcher{MatchingFunc: repeatMatch, ID: repeatMatcherName}) 77 | matchers = append(matchers, match.Matcher{MatchingFunc: sequenceMatch, ID: sequenceMatcherName}) 78 | matchers = append(matchers, match.Matcher{MatchingFunc: l33tMatch, ID: L33TMatcherName}) 79 | matchers = append(matchers, match.Matcher{MatchingFunc: dateSepMatcher, ID: dateSepMatcherName}) 80 | matchers = append(matchers, match.Matcher{MatchingFunc: dateWithoutSepMatch, ID: dateWithOutSepMatcherName}) 81 | 82 | } 83 | -------------------------------------------------------------------------------- /matching/matching_test.go: -------------------------------------------------------------------------------- 1 | package matching 2 | 3 | import ( 4 | "log" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/nbutton23/zxcvbn-go/match" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | //DateSepMatch("1991-09-11jibjab11.9.1991") 13 | //[{date 16 25 . 9 11 1991} {date 0 10 - 9 11 1991}] 14 | 15 | //TODO think about how to write this test. . . 16 | //func TestDateSepMatch(t *testing.T) { 17 | // matches := dateSepMatchHelper("1991-09-11jibjab11.9.1991") 18 | // 19 | // assert.Len(t, matches, 2, "Length should be 2") 20 | // 21 | // for _, match := range matches { 22 | // if match.Separator == "." { 23 | // assert.Equal(t, 16, match.I) 24 | // assert.Equal(t, 25, match.J) 25 | // assert.Equal(t, int64(9), match.Day) 26 | // assert.Equal(t, int64(11), match.Month) 27 | // assert.Equal(t, int64(1991), match.Year) 28 | // } else { 29 | // assert.Equal(t, 0, match.I) 30 | // assert.Equal(t, 10, match.J) 31 | // assert.Equal(t, int64(9), match.Day) 32 | // assert.Equal(t, int64(11), match.Month) 33 | // assert.Equal(t, int64(1991), match.Year) 34 | // } 35 | // } 36 | // 37 | //} 38 | // 39 | func TestRepeatMatch(t *testing.T) { 40 | //aaaBbBb 41 | matches := repeatMatch("aaabBbB") 42 | 43 | assert.Len(t, matches, 2, "Lenght should be 2") 44 | 45 | for _, match := range matches { 46 | if strings.ToLower(match.DictionaryName) == "b" { 47 | assert.Equal(t, 3, match.I) 48 | assert.Equal(t, 6, match.J) 49 | assert.Equal(t, "bBbB", match.Token) 50 | assert.NotZero(t, match.Entropy, "Entropy should be set") 51 | } else { 52 | assert.Equal(t, 0, match.I) 53 | assert.Equal(t, 2, match.J) 54 | assert.Equal(t, "aaa", match.Token) 55 | assert.NotZero(t, match.Entropy, "Entropy should be set") 56 | 57 | } 58 | } 59 | } 60 | 61 | func TestSequenceMatch(t *testing.T) { 62 | //abcdjibjacLMNOPjibjac1234 => abcd LMNOP 1234 63 | 64 | matches := sequenceMatch("abcdjibjacLMNOPjibjac1234") 65 | assert.Len(t, matches, 3, "Lenght should be 3") 66 | 67 | for _, match := range matches { 68 | if match.DictionaryName == "lower" { 69 | assert.Equal(t, 0, match.I) 70 | assert.Equal(t, 3, match.J) 71 | assert.Equal(t, "abcd", match.Token) 72 | assert.NotZero(t, match.Entropy, "Entropy should be set") 73 | } else if match.DictionaryName == "upper" { 74 | assert.Equal(t, 10, match.I) 75 | assert.Equal(t, 14, match.J) 76 | assert.Equal(t, "LMNOP", match.Token) 77 | assert.NotZero(t, match.Entropy, "Entropy should be set") 78 | } else if match.DictionaryName == "digits" { 79 | assert.Equal(t, 21, match.I) 80 | assert.Equal(t, 24, match.J) 81 | assert.Equal(t, "1234", match.Token) 82 | assert.NotZero(t, match.Entropy, "Entropy should be set") 83 | } else { 84 | assert.True(t, false, "Unknow dictionary") 85 | } 86 | } 87 | } 88 | 89 | func TestSpatialMatchQwerty(t *testing.T) { 90 | matches := spatialMatch("qwerty") 91 | assert.Len(t, matches, 1, "Lenght should be 1") 92 | assert.NotZero(t, matches[0].Entropy, "Entropy should be set") 93 | 94 | matches = spatialMatch("asdf") 95 | assert.Len(t, matches, 1, "Lenght should be 1") 96 | assert.NotZero(t, matches[0].Entropy, "Entropy should be set") 97 | 98 | } 99 | 100 | func TestSpatialMatchDvorak(t *testing.T) { 101 | matches := spatialMatch("aoeuidhtns") 102 | assert.Len(t, matches, 1, "Lenght should be 1") 103 | assert.NotZero(t, matches[0].Entropy, "Entropy should be set") 104 | 105 | } 106 | 107 | func TestDictionaryMatch(t *testing.T) { 108 | var matches []match.Match 109 | for _, dicMatcher := range dictionaryMatchers { 110 | matchesTemp := dicMatcher.MatchingFunc("first") 111 | matches = append(matches, matchesTemp...) 112 | } 113 | 114 | assert.Len(t, matches, 4, "Lenght should be 4") 115 | for _, match := range matches { 116 | assert.NotZero(t, match.Entropy, "Entropy should be set") 117 | 118 | } 119 | 120 | } 121 | 122 | func TestDateWithoutSepMatch(t *testing.T) { 123 | matches := dateWithoutSepMatch("11091991") 124 | assert.Len(t, matches, 1, "Lenght should be 1") 125 | 126 | matches = dateWithoutSepMatch("20010911") 127 | assert.Len(t, matches, 1, "Lenght should be 1") 128 | log.Println(matches) 129 | 130 | //matches := dateWithoutSepMatch("110991") 131 | //assert.Len(t, matches, 21, "Lenght should be blarg") 132 | } 133 | -------------------------------------------------------------------------------- /matching/repeatMatch.go: -------------------------------------------------------------------------------- 1 | package matching 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/nbutton23/zxcvbn-go/entropy" 7 | "github.com/nbutton23/zxcvbn-go/match" 8 | ) 9 | 10 | const repeatMatcherName = "REPEAT" 11 | 12 | //FilterRepeatMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher 13 | func FilterRepeatMatcher(m match.Matcher) bool { 14 | return m.ID == repeatMatcherName 15 | } 16 | 17 | func repeatMatch(password string) []match.Match { 18 | var matches []match.Match 19 | 20 | //Loop through password. if current == prev currentStreak++ else if currentStreak > 2 {buildMatch; currentStreak = 1} prev = current 21 | var current, prev string 22 | currentStreak := 1 23 | var i int 24 | var char rune 25 | for i, char = range password { 26 | current = string(char) 27 | if i == 0 { 28 | prev = current 29 | continue 30 | } 31 | 32 | if strings.ToLower(current) == strings.ToLower(prev) { 33 | currentStreak++ 34 | 35 | } else if currentStreak > 2 { 36 | iPos := i - currentStreak 37 | jPos := i - 1 38 | matchRepeat := match.Match{ 39 | Pattern: "repeat", 40 | I: iPos, 41 | J: jPos, 42 | Token: password[iPos : jPos+1], 43 | DictionaryName: prev} 44 | matchRepeat.Entropy = entropy.RepeatEntropy(matchRepeat) 45 | matches = append(matches, matchRepeat) 46 | currentStreak = 1 47 | } else { 48 | currentStreak = 1 49 | } 50 | 51 | prev = current 52 | } 53 | 54 | if currentStreak > 2 { 55 | iPos := i - currentStreak + 1 56 | jPos := i 57 | matchRepeat := match.Match{ 58 | Pattern: "repeat", 59 | I: iPos, 60 | J: jPos, 61 | Token: password[iPos : jPos+1], 62 | DictionaryName: prev} 63 | matchRepeat.Entropy = entropy.RepeatEntropy(matchRepeat) 64 | matches = append(matches, matchRepeat) 65 | } 66 | return matches 67 | } 68 | -------------------------------------------------------------------------------- /matching/sequenceMatch.go: -------------------------------------------------------------------------------- 1 | package matching 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/nbutton23/zxcvbn-go/entropy" 7 | "github.com/nbutton23/zxcvbn-go/match" 8 | ) 9 | 10 | const sequenceMatcherName = "SEQ" 11 | 12 | //FilterSequenceMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher 13 | func FilterSequenceMatcher(m match.Matcher) bool { 14 | return m.ID == sequenceMatcherName 15 | } 16 | 17 | func sequenceMatch(password string) []match.Match { 18 | var matches []match.Match 19 | for i := 0; i < len(password); { 20 | j := i + 1 21 | var seq string 22 | var seqName string 23 | seqDirection := 0 24 | for seqCandidateName, seqCandidate := range sequences { 25 | iN := strings.Index(seqCandidate, string(password[i])) 26 | var jN int 27 | if j < len(password) { 28 | jN = strings.Index(seqCandidate, string(password[j])) 29 | } else { 30 | jN = -1 31 | } 32 | 33 | if iN > -1 && jN > -1 { 34 | direction := jN - iN 35 | if direction == 1 || direction == -1 { 36 | seq = seqCandidate 37 | seqName = seqCandidateName 38 | seqDirection = direction 39 | break 40 | } 41 | } 42 | 43 | } 44 | 45 | if seq != "" { 46 | for { 47 | var prevN, curN int 48 | if j < len(password) { 49 | prevChar, curChar := password[j-1], password[j] 50 | prevN, curN = strings.Index(seq, string(prevChar)), strings.Index(seq, string(curChar)) 51 | } 52 | 53 | if j == len(password) || curN-prevN != seqDirection { 54 | if j-i > 2 { 55 | matchSequence := match.Match{ 56 | Pattern: "sequence", 57 | I: i, 58 | J: j - 1, 59 | Token: password[i:j], 60 | DictionaryName: seqName, 61 | } 62 | 63 | matchSequence.Entropy = entropy.SequenceEntropy(matchSequence, len(seq), (seqDirection == 1)) 64 | matches = append(matches, matchSequence) 65 | } 66 | break 67 | } else { 68 | j++ 69 | } 70 | 71 | } 72 | } 73 | i = j 74 | } 75 | return matches 76 | } 77 | -------------------------------------------------------------------------------- /matching/spatialMatch.go: -------------------------------------------------------------------------------- 1 | package matching 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/nbutton23/zxcvbn-go/adjacency" 7 | "github.com/nbutton23/zxcvbn-go/entropy" 8 | "github.com/nbutton23/zxcvbn-go/match" 9 | ) 10 | 11 | const spatialMatcherName = "SPATIAL" 12 | 13 | //FilterSpatialMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher 14 | func FilterSpatialMatcher(m match.Matcher) bool { 15 | return m.ID == spatialMatcherName 16 | } 17 | 18 | func spatialMatch(password string) (matches []match.Match) { 19 | for _, graph := range adjacencyGraphs { 20 | if graph.Graph != nil { 21 | matches = append(matches, spatialMatchHelper(password, graph)...) 22 | } 23 | } 24 | return matches 25 | } 26 | 27 | func spatialMatchHelper(password string, graph adjacency.Graph) (matches []match.Match) { 28 | 29 | for i := 0; i < len(password)-1; { 30 | j := i + 1 31 | lastDirection := -99 //an int that it should never be! 32 | turns := 0 33 | shiftedCount := 0 34 | 35 | for { 36 | prevChar := password[j-1] 37 | found := false 38 | foundDirection := -1 39 | curDirection := -1 40 | //My graphs seem to be wrong. . . and where the hell is qwerty 41 | adjacents := graph.Graph[string(prevChar)] 42 | //Consider growing pattern by one character if j hasn't gone over the edge 43 | if j < len(password) { 44 | curChar := password[j] 45 | for _, adj := range adjacents { 46 | curDirection++ 47 | 48 | if strings.Index(adj, string(curChar)) != -1 { 49 | found = true 50 | foundDirection = curDirection 51 | 52 | if strings.Index(adj, string(curChar)) == 1 { 53 | //index 1 in the adjacency means the key is shifted, 0 means unshifted: A vs a, % vs 5, etc. 54 | //for example, 'q' is adjacent to the entry '2@'. @ is shifted w/ index 1, 2 is unshifted. 55 | shiftedCount++ 56 | } 57 | 58 | if lastDirection != foundDirection { 59 | //adding a turn is correct even in the initial case when last_direction is null: 60 | //every spatial pattern starts with a turn. 61 | turns++ 62 | lastDirection = foundDirection 63 | } 64 | break 65 | } 66 | } 67 | } 68 | 69 | //if the current pattern continued, extend j and try to grow again 70 | if found { 71 | j++ 72 | } else { 73 | //otherwise push the pattern discovered so far, if any... 74 | //don't consider length 1 or 2 chains. 75 | if j-i > 2 { 76 | matchSpc := match.Match{Pattern: "spatial", I: i, J: j - 1, Token: password[i:j], DictionaryName: graph.Name} 77 | matchSpc.Entropy = entropy.SpatialEntropy(matchSpc, turns, shiftedCount) 78 | matches = append(matches, matchSpc) 79 | } 80 | //. . . and then start a new search from the rest of the password 81 | i = j 82 | break 83 | } 84 | } 85 | 86 | } 87 | return matches 88 | } 89 | -------------------------------------------------------------------------------- /scoring/scoring.go: -------------------------------------------------------------------------------- 1 | package scoring 2 | 3 | import ( 4 | "fmt" 5 | "github.com/nbutton23/zxcvbn-go/entropy" 6 | "github.com/nbutton23/zxcvbn-go/match" 7 | "github.com/nbutton23/zxcvbn-go/utils/math" 8 | "math" 9 | "sort" 10 | ) 11 | 12 | const ( 13 | //for a hash function like bcrypt/scrypt/PBKDF2, 10ms per guess is a safe lower bound. 14 | //(usually a guess would take longer -- this assumes fast hardware and a small work factor.) 15 | //adjust for your site accordingly if you use another hash function, possibly by 16 | //several orders of magnitude! 17 | singleGuess float64 = 0.010 18 | numAttackers float64 = 100 //Cores used to make guesses 19 | secondsPerGuess float64 = singleGuess / numAttackers 20 | ) 21 | 22 | // MinEntropyMatch is the lowest entropy match found 23 | type MinEntropyMatch struct { 24 | Password string 25 | Entropy float64 26 | MatchSequence []match.Match 27 | CrackTime float64 28 | CrackTimeDisplay string 29 | Score int 30 | CalcTime float64 31 | } 32 | 33 | /* 34 | MinimumEntropyMatchSequence returns the minimum entropy 35 | 36 | Takes a list of overlapping matches, returns the non-overlapping sublist with 37 | minimum entropy. O(nm) dp alg for length-n password with m candidate matches. 38 | */ 39 | func MinimumEntropyMatchSequence(password string, matches []match.Match) MinEntropyMatch { 40 | bruteforceCardinality := float64(entropy.CalcBruteForceCardinality(password)) 41 | upToK := make([]float64, len(password)) 42 | backPointers := make([]match.Match, len(password)) 43 | 44 | for k := 0; k < len(password); k++ { 45 | upToK[k] = get(upToK, k-1) + math.Log2(bruteforceCardinality) 46 | 47 | for _, match := range matches { 48 | if match.J != k { 49 | continue 50 | } 51 | 52 | i, j := match.I, match.J 53 | //see if best entropy up to i-1 + entropy of match is less that current min at j 54 | upTo := get(upToK, i-1) 55 | candidateEntropy := upTo + match.Entropy 56 | 57 | if candidateEntropy < upToK[j] { 58 | upToK[j] = candidateEntropy 59 | match.Entropy = candidateEntropy 60 | backPointers[j] = match 61 | } 62 | } 63 | } 64 | 65 | //walk backwards and decode the best sequence 66 | var matchSequence []match.Match 67 | passwordLen := len(password) 68 | passwordLen-- 69 | for k := passwordLen; k >= 0; { 70 | match := backPointers[k] 71 | if match.Pattern != "" { 72 | matchSequence = append(matchSequence, match) 73 | k = match.I - 1 74 | 75 | } else { 76 | k-- 77 | } 78 | 79 | } 80 | sort.Sort(match.Matches(matchSequence)) 81 | 82 | makeBruteForceMatch := func(i, j int) match.Match { 83 | return match.Match{Pattern: "bruteforce", 84 | I: i, 85 | J: j, 86 | Token: password[i : j+1], 87 | Entropy: math.Log2(math.Pow(bruteforceCardinality, float64(j-i)))} 88 | 89 | } 90 | 91 | k := 0 92 | var matchSequenceCopy []match.Match 93 | for _, match := range matchSequence { 94 | i, j := match.I, match.J 95 | if i-k > 0 { 96 | matchSequenceCopy = append(matchSequenceCopy, makeBruteForceMatch(k, i-1)) 97 | } 98 | k = j + 1 99 | matchSequenceCopy = append(matchSequenceCopy, match) 100 | } 101 | 102 | if k < len(password) { 103 | matchSequenceCopy = append(matchSequenceCopy, makeBruteForceMatch(k, len(password)-1)) 104 | } 105 | var minEntropy float64 106 | if len(password) == 0 { 107 | minEntropy = float64(0) 108 | } else { 109 | minEntropy = upToK[len(password)-1] 110 | } 111 | 112 | crackTime := roundToXDigits(entropyToCrackTime(minEntropy), 3) 113 | return MinEntropyMatch{Password: password, 114 | Entropy: roundToXDigits(minEntropy, 3), 115 | MatchSequence: matchSequenceCopy, 116 | CrackTime: crackTime, 117 | CrackTimeDisplay: displayTime(crackTime), 118 | Score: crackTimeToScore(crackTime)} 119 | 120 | } 121 | func get(a []float64, i int) float64 { 122 | if i < 0 || i >= len(a) { 123 | return float64(0) 124 | } 125 | 126 | return a[i] 127 | } 128 | 129 | func entropyToCrackTime(entropy float64) float64 { 130 | crackTime := (0.5 * math.Pow(float64(2), entropy)) * secondsPerGuess 131 | 132 | return crackTime 133 | } 134 | 135 | func roundToXDigits(number float64, digits int) float64 { 136 | return zxcvbnmath.Round(number, .5, digits) 137 | } 138 | 139 | func displayTime(seconds float64) string { 140 | formater := "%.1f %s" 141 | minute := float64(60) 142 | hour := minute * float64(60) 143 | day := hour * float64(24) 144 | month := day * float64(31) 145 | year := month * float64(12) 146 | century := year * float64(100) 147 | 148 | if seconds < minute { 149 | return "instant" 150 | } else if seconds < hour { 151 | return fmt.Sprintf(formater, (1 + math.Ceil(seconds/minute)), "minutes") 152 | } else if seconds < day { 153 | return fmt.Sprintf(formater, (1 + math.Ceil(seconds/hour)), "hours") 154 | } else if seconds < month { 155 | return fmt.Sprintf(formater, (1 + math.Ceil(seconds/day)), "days") 156 | } else if seconds < year { 157 | return fmt.Sprintf(formater, (1 + math.Ceil(seconds/month)), "months") 158 | } else if seconds < century { 159 | return fmt.Sprintf(formater, (1 + math.Ceil(seconds/century)), "years") 160 | } else { 161 | return "centuries" 162 | } 163 | } 164 | 165 | func crackTimeToScore(seconds float64) int { 166 | if seconds < math.Pow(10, 2) { 167 | return 0 168 | } else if seconds < math.Pow(10, 4) { 169 | return 1 170 | } else if seconds < math.Pow(10, 6) { 171 | return 2 172 | } else if seconds < math.Pow(10, 8) { 173 | return 3 174 | } 175 | 176 | return 4 177 | } 178 | -------------------------------------------------------------------------------- /testapp/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/nbutton23/zxcvbn-go" 9 | ) 10 | 11 | func main() { 12 | for { 13 | fmt.Println("Enter password or Ctrl-c to exit:") 14 | reader := bufio.NewReader(os.Stdin) 15 | password, _ := reader.ReadString('\n') 16 | //password := "Testaaatyhg890l33t" 17 | 18 | passwordStenght := zxcvbn.PasswordStrength(password, nil) 19 | 20 | fmt.Printf("Password score (0-4): %d\nEstimated entropy (bit): %f\nEstimated time to crack: %s\n\n", 21 | passwordStenght.Score, 22 | passwordStenght.Entropy, 23 | passwordStenght.CrackTimeDisplay, 24 | ) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /utils/math/mathutils.go: -------------------------------------------------------------------------------- 1 | package zxcvbnmath 2 | 3 | import "math" 4 | 5 | /* 6 | NChoseK http://blog.plover.com/math/choose.html 7 | I am surprised that I have to define these. . . Maybe i just didn't look hard enough for a lib. 8 | */ 9 | func NChoseK(n, k float64) float64 { 10 | if k > n { 11 | return 0 12 | } else if k == 0 { 13 | return 1 14 | } 15 | 16 | var r float64 = 1 17 | 18 | for d := float64(1); d <= k; d++ { 19 | r *= n 20 | r /= d 21 | n-- 22 | } 23 | 24 | return r 25 | } 26 | 27 | // Round a number 28 | func Round(val float64, roundOn float64, places int) (newVal float64) { 29 | var round float64 30 | pow := math.Pow(10, float64(places)) 31 | digit := pow * val 32 | _, div := math.Modf(digit) 33 | if div >= roundOn { 34 | round = math.Ceil(digit) 35 | } else { 36 | round = math.Floor(digit) 37 | } 38 | newVal = round / pow 39 | return 40 | } 41 | -------------------------------------------------------------------------------- /utils/math/mathutils_test.go: -------------------------------------------------------------------------------- 1 | package zxcvbnmath 2 | 3 | import ( 4 | "github.com/stretchr/testify/assert" 5 | "testing" 6 | ) 7 | 8 | func TestNchoseK100and2(t *testing.T) { 9 | nCk := NChoseK(100, 2) 10 | 11 | assert.Equal(t, float64(4950), nCk, "100 chose 2 should equal 4950") 12 | } 13 | 14 | func TestNChoseKwereNlessK(t *testing.T) { 15 | nCk := NChoseK(1, 2) 16 | 17 | assert.Equal(t, float64(0), nCk, "When n is less than k always 0") 18 | } 19 | 20 | func TestNChoseKWereKis0(t *testing.T) { 21 | nCk := NChoseK(50, 0) 22 | 23 | assert.Equal(t, float64(1), nCk, "When K is 0 then 1") 24 | } 25 | -------------------------------------------------------------------------------- /zxcvbn.go: -------------------------------------------------------------------------------- 1 | package zxcvbn 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/nbutton23/zxcvbn-go/match" 7 | "github.com/nbutton23/zxcvbn-go/matching" 8 | "github.com/nbutton23/zxcvbn-go/scoring" 9 | "github.com/nbutton23/zxcvbn-go/utils/math" 10 | ) 11 | 12 | // PasswordStrength takes a password, userInputs and optional filters and returns a MinEntropyMatch 13 | func PasswordStrength(password string, userInputs []string, filters ...func(match.Matcher) bool) scoring.MinEntropyMatch { 14 | start := time.Now() 15 | matches := matching.Omnimatch(password, userInputs, filters...) 16 | result := scoring.MinimumEntropyMatchSequence(password, matches) 17 | end := time.Now() 18 | 19 | calcTime := end.Nanosecond() - start.Nanosecond() 20 | result.CalcTime = zxcvbnmath.Round(float64(calcTime)*time.Nanosecond.Seconds(), .5, 3) 21 | return result 22 | } 23 | -------------------------------------------------------------------------------- /zxcvbn_test.go: -------------------------------------------------------------------------------- 1 | package zxcvbn 2 | 3 | import ( 4 | "math" 5 | "testing" 6 | ) 7 | 8 | /** 9 | Use these test to see how close to feature parity the library is. 10 | */ 11 | 12 | const ( 13 | allowableError = float64(0.05) 14 | ) 15 | 16 | func TestPasswordStrength(t *testing.T) { 17 | 18 | // Expected calculated by running zxcvbn-python 19 | runTest(t, "zxcvbn", float64(6.845490050944376)) 20 | runTest(t, "Tr0ub4dour&3", float64(17.296)) 21 | runTest(t, "qwER43@!", float64(26.44)) 22 | runTest(t, "correcthorsebatterystaple", float64(45.212)) 23 | runTest(t, "coRrecth0rseba++ery9.23.2007staple$", float64(66.018)) 24 | runTest(t, "D0g..................", float64(20.678)) 25 | runTest(t, "abcdefghijk987654321", float64(11.951)) 26 | runTest(t, "neverforget", float64(2)) // I think this is wrong. . . 27 | runTest(t, "13/3/1997", float64(2)) // I think this is wrong. . . 28 | runTest(t, "neverforget13/3/1997", float64(32.628)) 29 | runTest(t, "1qaz2wsx3edc", float64(19.314)) 30 | runTest(t, "temppass22", float64(22.179)) 31 | runTest(t, "briansmith", float64(4.322)) 32 | runTest(t, "briansmith4mayor", float64(18.64)) 33 | runTest(t, "password1", float64(2.0)) 34 | runTest(t, "viking", float64(7.531)) 35 | runTest(t, "thx1138", float64(7.426)) 36 | runTest(t, "ScoRpi0ns", float64(20.621)) 37 | runTest(t, "do you know", float64(4.585)) 38 | runTest(t, "ryanhunter2000", float64(14.506)) 39 | runTest(t, "rianhunter2000", float64(21.734)) 40 | runTest(t, "asdfghju7654rewq", float64(29.782)) 41 | runTest(t, "AOEUIDHG&*()LS_", float64(33.254)) 42 | runTest(t, "12345678", float64(1.585)) 43 | runTest(t, "defghi6789", float64(12.607)) 44 | runTest(t, "rosebud", float64(7.937)) 45 | runTest(t, "Rosebud", float64(8.937)) 46 | runTest(t, "ROSEBUD", float64(8.937)) 47 | runTest(t, "rosebuD", float64(8.937)) 48 | runTest(t, "ros3bud99", float64(19.276)) 49 | runTest(t, "r0s3bud99", float64(19.276)) 50 | runTest(t, "R0$38uD99", float64(34.822)) 51 | runTest(t, "verlineVANDERMARK", float64(26.293)) 52 | runTest(t, "eheuczkqyq", float64(42.813)) 53 | runTest(t, "rWibMFACxAUGZmxhVncy", float64(104.551)) 54 | runTest(t, "Ba9ZyWABu99[BK#6MBgbH88Tofv)vs$", float64(161.278)) 55 | } 56 | 57 | var formatString = "%s : error should be less than %.2f Acctual error: %.4f Expected entropy %.4f Actual entropy %.4f \n" 58 | 59 | func runTest(t *testing.T, password string, pythonEntropy float64) { 60 | 61 | goEntropy := GoPasswordStrength(password, nil) 62 | perror := math.Abs(goEntropy-pythonEntropy) / pythonEntropy 63 | 64 | if perror > allowableError { 65 | t.Logf(formatString, password, allowableError, perror, pythonEntropy, goEntropy) 66 | 67 | // t.Fail() 68 | } 69 | } 70 | 71 | func GoPasswordStrength(password string, userInputs []string) float64 { 72 | return PasswordStrength(password, userInputs).Entropy 73 | } 74 | --------------------------------------------------------------------------------