// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. package app import ( "crypto/rand" "math/big" ) const ( passwordSpecialChars = "!$%^&*(),." passwordNumbers = "0123456789" passwordUpperCaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" passwordLowerCaseLetters = "abcdefghijklmnopqrstuvwxyz" passwordAllChars = passwordSpecialChars + passwordNumbers + passwordUpperCaseLetters + passwordLowerCaseLetters ) func randInt(maxInt int) (int, error) { val, err := rand.Int(rand.Reader, big.NewInt(int64(maxInt))) if err != nil { return 0, err } return int(val.Int64()), nil } func generatePassword(minimumLength int) (string, error) { upperIdx, err := randInt(len(passwordUpperCaseLetters)) if err != nil { return "", err } numberIdx, err := randInt(len(passwordNumbers)) if err != nil { return "", err } lowerIdx, err := randInt(len(passwordLowerCaseLetters)) if err != nil { return "", err } specialIdx, err := randInt(len(passwordSpecialChars)) if err != nil { return "", err } // Make sure we are guaranteed at least one of each type to meet any possible password complexity requirements. password := string([]rune(passwordUpperCaseLetters)[upperIdx]) + string([]rune(passwordNumbers)[numberIdx]) + string([]rune(passwordLowerCaseLetters)[lowerIdx]) + string([]rune(passwordSpecialChars)[specialIdx]) for len(password) < minimumLength { i, err := randInt(len(passwordAllChars)) if err != nil { return "", err } password = password + string([]rune(passwordAllChars)[i]) } return password, nil }