github.com/verrazzano/verrazzano@v1.7.1/pkg/security/password/password.go (about) 1 // Copyright (c) 2021, 2022, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package password 5 6 import ( 7 "crypto/rand" 8 b64 "encoding/base64" 9 "fmt" 10 "regexp" 11 "strings" 12 ) 13 14 const mask = "******" 15 16 const ( 17 modeAlphaNum = 0 18 modeAlphaLower = 1 19 ) 20 21 // GeneratePassword will generate a password of length 22 func GeneratePassword(length int) (string, error) { 23 return GeneratePasswordUsingMode(length, modeAlphaNum) 24 } 25 26 // GenerateRandomAlphaLower will generate a lower-case alpha string of length 27 // Should be used only for generating semi-unique, non-cryptographic, non-secret strings -- NOT passwords! 28 func GenerateRandomAlphaLower(length int) (string, error) { 29 return GeneratePasswordUsingMode(length, modeAlphaLower) 30 } 31 32 // GeneratePasswordUsingMode will generate a password of length with mode 33 func GeneratePasswordUsingMode(length int, mode int) (string, error) { 34 if length < 1 { 35 return "", fmt.Errorf("cannot create password of length %d", length) 36 } 37 // Enlarge buffer so plenty of room is left when special characters are stripped out 38 b := make([]byte, length*4) 39 _, err := rand.Read(b) 40 if err != nil { 41 return "", err 42 } 43 pw := b64.StdEncoding.EncodeToString(b) 44 if mode == modeAlphaNum { 45 pw, err = makeAlphaNumeric(pw) 46 } else { 47 pw, err = makeAlphaLower(pw) 48 } 49 if err != nil { 50 return "", err 51 } 52 return pw[:length], nil 53 } 54 55 // makeAlphaNumeric removes all special characters from a password string 56 func makeAlphaNumeric(input string) (string, error) { 57 // Make a Regex to say we only want letters and numbers 58 reg, err := regexp.Compile("[^a-zA-Z0-9]+") 59 if err != nil { 60 return "", err 61 } 62 return reg.ReplaceAllString(input, ""), nil 63 } 64 65 // makeAlphaLower removes all special characters and numbers from a string, and lowercases the result 66 func makeAlphaLower(input string) (string, error) { 67 // Make a Regex to say we only want letters 68 reg, err := regexp.Compile("[^a-zA-Z]+") 69 if err != nil { 70 return "", err 71 } 72 return strings.ToLower(reg.ReplaceAllString(input, "")), nil 73 } 74 75 // MaskFunction creates a function intended to mask passwords which are substrings in other strings 76 // f := MaskFunction("pw=") creates a function that masks strings like so: 77 // f("pw=xyz") = "pw=******" 78 func MaskFunction(prefix string) func(string) string { 79 re := regexp.MustCompile(fmt.Sprintf(`%s.*?(?:\s|$)`, prefix)) 80 return func(s string) string { 81 replace := fmt.Sprintf("%s%s", prefix, mask) 82 matches := re.FindAllString(s, -1) 83 for _, match := range matches { 84 ch := match[len(match)-1] 85 var m string 86 if ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r' { 87 m = match[:len(match)-1] // preserve last non-masked character if there is one 88 } else { 89 m = match 90 } 91 s = strings.ReplaceAll(s, m, replace) 92 } 93 return s 94 } 95 }