Initial
This commit is contained in:
commit
8889eccef6
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/.idea
|
||||
/passgen
|
10
dictionary/sets/ascii_lowercase.go
Normal file
10
dictionary/sets/ascii_lowercase.go
Normal file
@ -0,0 +1,10 @@
|
||||
package sets
|
||||
|
||||
func AsciiLowercase() (dict []int) {
|
||||
// Print lowercase letters (ASCII 97 to 122)
|
||||
for i := 97; i <= 122; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
10
dictionary/sets/ascii_uppercase.go
Normal file
10
dictionary/sets/ascii_uppercase.go
Normal file
@ -0,0 +1,10 @@
|
||||
package sets
|
||||
|
||||
func AsciiUppercase() (dict []int) {
|
||||
// Print uppercase letters (ASCII 65 to 90)
|
||||
for i := 65; i <= 90; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
50
dictionary/sets/chinese.go
Normal file
50
dictionary/sets/chinese.go
Normal file
@ -0,0 +1,50 @@
|
||||
package sets
|
||||
|
||||
func Chinese() (dict []int) {
|
||||
// CJK Unified Ideographs (Common)
|
||||
for i := 0x4E00; i <= 0x9FFF; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// CJK Unified Ideographs Extension A (Rare)
|
||||
for i := 0x3400; i <= 0x4DBF; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// CJK Unified Ideographs Extension B (Rare, historic)
|
||||
for i := 0x20000; i <= 0x2A6DF; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// CJK Unified Ideographs Extension C (Rare, historic)
|
||||
for i := 0x2A700; i <= 0x2B73F; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// CJK Unified Ideographs Extension D (Uncommon, some in current use)
|
||||
for i := 0x2B740; i <= 0x2B81F; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// CJK Unified Ideographs Extension E (Rare, historic)
|
||||
for i := 0x2B820; i <= 0x2CEAF; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// CJK Unified Ideographs Extension F (Rare, historic)
|
||||
for i := 0x2CEB0; i <= 0x2EBEF; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// CJK Unified Ideographs Extension G (Rare, historic)
|
||||
for i := 0x30000; i <= 0x3134F; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// CJK Unified Ideographs Extension H (Rare, historic)
|
||||
for i := 0x31350; i <= 0x323AF; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
37
dictionary/sets/cyrillic.go
Normal file
37
dictionary/sets/cyrillic.go
Normal file
@ -0,0 +1,37 @@
|
||||
package sets
|
||||
|
||||
func Cyrillic() (dict []int) {
|
||||
// Cyrillic: U+0400–U+04FF (256 characters)
|
||||
for i := 0x0400; i <= 0x04FF; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// Cyrillic Supplement: U+0500–U+052F (48 characters)
|
||||
for i := 0x0500; i <= 0x052F; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// Cyrillic Extended-A: U+2DE0–U+2DFF (32 characters)
|
||||
for i := 0x2DE0; i <= 0x2DFF; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// Cyrillic Extended-B: U+A640–U+A69F (96 characters)
|
||||
for i := 0xA640; i <= 0xA69F; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// Cyrillic Extended-C: U+1C80–U+1C8F (9 characters)
|
||||
for i := 0x1C80; i <= 0x1C8F; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// Cyrillic Extended-D: U+1E030–U+1E08F (63 characters)
|
||||
for i := 0x1E030; i <= 0x1E08F; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
dict = append(dict, []int{0x1D2B, 0x1D78}...)
|
||||
|
||||
return
|
||||
}
|
30
dictionary/sets/japanese.go
Normal file
30
dictionary/sets/japanese.go
Normal file
@ -0,0 +1,30 @@
|
||||
package sets
|
||||
|
||||
func Japanese() (dict []int) {
|
||||
// Japanese-style punctuation
|
||||
for i := 0x3000; i <= 0x303F; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// Hiragana
|
||||
for i := 0x3040; i <= 0x309F; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// Katakana
|
||||
for i := 0x30A0; i <= 0x30FF; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// Full-width roman characters and half-width katakana
|
||||
for i := 0xFF00; i <= 0xFFEF; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
// CJK unified ideographs (common and uncommon kanji)
|
||||
for i := 0x4E00; i <= 0x9FAF; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
10
dictionary/sets/numbers.go
Normal file
10
dictionary/sets/numbers.go
Normal file
@ -0,0 +1,10 @@
|
||||
package sets
|
||||
|
||||
func Numbers() (dict []int) {
|
||||
// Print numbers (ASCII 48 to 57)
|
||||
for i := 48; i <= 57; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
7
dictionary/sets/space.go
Normal file
7
dictionary/sets/space.go
Normal file
@ -0,0 +1,7 @@
|
||||
package sets
|
||||
|
||||
func Space() (dict []int) {
|
||||
dict = append(dict, ' ')
|
||||
|
||||
return
|
||||
}
|
10
dictionary/sets/special_chars.go
Normal file
10
dictionary/sets/special_chars.go
Normal file
@ -0,0 +1,10 @@
|
||||
package sets
|
||||
|
||||
func SpecialChars() (dict []int) {
|
||||
// Print special symbols (ASCII 33 to 47)
|
||||
for i := 33; i <= 47; i++ {
|
||||
dict = append(dict, i)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
14
dictionary/shuffle.go
Normal file
14
dictionary/shuffle.go
Normal file
@ -0,0 +1,14 @@
|
||||
package dictionary
|
||||
|
||||
import (
|
||||
"math/rand/v2"
|
||||
)
|
||||
|
||||
func ShuffleDictionarySet(slice []int) []int {
|
||||
for i := len(slice) - 1; i > 0; i-- {
|
||||
j := rand.IntN(i + 1)
|
||||
slice[i], slice[j] = slice[j], slice[i]
|
||||
}
|
||||
|
||||
return slice
|
||||
}
|
48
generator.go
Normal file
48
generator.go
Normal file
@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import "math/rand/v2"
|
||||
|
||||
func generatePassword(sets [][]int, passwordLength int) []int {
|
||||
numSets := len(sets)
|
||||
totalLength := 0
|
||||
for _, set := range sets {
|
||||
totalLength += len(set)
|
||||
}
|
||||
|
||||
props := make([]float64, numSets)
|
||||
for i := range props {
|
||||
props[i] = float64(len(sets[i])) / float64(totalLength)
|
||||
}
|
||||
|
||||
numChars := make([]int, numSets)
|
||||
for i := range numChars {
|
||||
numChars[i] = int(props[i] * float64(passwordLength))
|
||||
if numChars[i] == 0 {
|
||||
numChars[i] = 1
|
||||
}
|
||||
}
|
||||
|
||||
totalChars := 0
|
||||
for _, n := range numChars {
|
||||
totalChars += n
|
||||
}
|
||||
|
||||
if totalChars < passwordLength {
|
||||
numChars[0]++
|
||||
} else if totalChars > passwordLength {
|
||||
numChars[numSets-1]--
|
||||
}
|
||||
|
||||
password := make([]int, 0, passwordLength)
|
||||
for i, set := range sets {
|
||||
for j := 0; j < numChars[i]; j++ {
|
||||
password = append(password, set[rand.IntN(len(set))])
|
||||
}
|
||||
}
|
||||
|
||||
rand.Shuffle(len(password), func(i, j int) {
|
||||
password[i], password[j] = password[j], password[i]
|
||||
})
|
||||
|
||||
return password
|
||||
}
|
5
go.mod
Normal file
5
go.mod
Normal file
@ -0,0 +1,5 @@
|
||||
module gitea.stuzer.link/stuzer05/passgen
|
||||
|
||||
go 1.20
|
||||
|
||||
require golang.org/x/text v0.9.0 // indirect
|
2
go.sum
Normal file
2
go.sum
Normal file
@ -0,0 +1,2 @@
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
91
main.go
Normal file
91
main.go
Normal file
@ -0,0 +1,91 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"gitea.stuzer.link/stuzer05/passgen/dictionary"
|
||||
"gitea.stuzer.link/stuzer05/passgen/dictionary/sets"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// password flags
|
||||
flagLen := flag.Int("L", 16, "length of the generated password")
|
||||
flagCount := flag.Int("c", 1, "how many passwords to generate")
|
||||
|
||||
// set flags
|
||||
flagSetAll := flag.Bool("all", false, "use all character sets")
|
||||
flagSetAsciiLowercase := flag.Bool("l", false, "use lowercase ascii characters")
|
||||
flagSetAsciiUppercase := flag.Bool("U", false, "use uppercase ascii characters")
|
||||
flagSetNumbers := flag.Bool("n", false, "use numbers")
|
||||
flagSetSpecialChars := flag.Bool("s", false, "use special characters")
|
||||
flagSetSpaces := flag.Bool("S", false, "use spaces")
|
||||
flagSetUnicodeJapanese := flag.Bool("unicode-japanese", false, "use unicode Japanese characters")
|
||||
flagSetUnicodeChinese := flag.Bool("unicode-chinese", false, "use unicode Chinese characters")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
// check password length
|
||||
if *flagLen <= 0 {
|
||||
fmt.Println("password length must be at least 1")
|
||||
}
|
||||
|
||||
// check password count
|
||||
if *flagCount <= 0 {
|
||||
fmt.Println("passwords count must be at least 1")
|
||||
}
|
||||
|
||||
// use all character sets
|
||||
if *flagSetAll {
|
||||
*flagSetAsciiLowercase = true
|
||||
*flagSetAsciiUppercase = true
|
||||
*flagSetNumbers = true
|
||||
*flagSetSpecialChars = true
|
||||
*flagSetSpaces = true
|
||||
|
||||
*flagSetUnicodeJapanese = true
|
||||
*flagSetUnicodeChinese = true
|
||||
}
|
||||
|
||||
// use default password preset no sets were requested
|
||||
if !*flagSetAll && !*flagSetAsciiLowercase && !*flagSetAsciiUppercase && !*flagSetNumbers && !*flagSetSpecialChars && !*flagSetSpaces && !*flagSetUnicodeJapanese && !*flagSetUnicodeChinese {
|
||||
*flagSetAsciiLowercase = true
|
||||
*flagSetAsciiUppercase = true
|
||||
*flagSetNumbers = true
|
||||
}
|
||||
|
||||
// select dictionaries
|
||||
var characterSets [][]int
|
||||
|
||||
if *flagSetAsciiLowercase {
|
||||
characterSets = append(characterSets, dictionary.ShuffleDictionarySet(sets.AsciiLowercase()))
|
||||
}
|
||||
if *flagSetAsciiUppercase {
|
||||
characterSets = append(characterSets, dictionary.ShuffleDictionarySet(sets.AsciiUppercase()))
|
||||
}
|
||||
if *flagSetNumbers {
|
||||
characterSets = append(characterSets, dictionary.ShuffleDictionarySet(sets.Numbers()))
|
||||
}
|
||||
if *flagSetSpecialChars {
|
||||
characterSets = append(characterSets, dictionary.ShuffleDictionarySet(sets.SpecialChars()))
|
||||
}
|
||||
if *flagSetSpaces {
|
||||
characterSets = append(characterSets, dictionary.ShuffleDictionarySet(sets.Space()))
|
||||
}
|
||||
|
||||
// unicode
|
||||
if *flagSetUnicodeJapanese {
|
||||
characterSets = append(characterSets, dictionary.ShuffleDictionarySet(sets.Japanese()))
|
||||
}
|
||||
if *flagSetUnicodeChinese {
|
||||
characterSets = append(characterSets, dictionary.ShuffleDictionarySet(sets.Chinese()))
|
||||
}
|
||||
|
||||
// generate passwords
|
||||
for i := 0; i < *flagCount; i++ {
|
||||
password := generatePassword(characterSets, *flagLen)
|
||||
|
||||
for _, i := range password {
|
||||
fmt.Printf("%c", i)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user