You've already forked nyx
							
							
				mirror of
				https://github.com/rls-moe/nyx
				synced 2025-10-31 12:04:15 +00:00 
			
		
		
		
	MVP, no mod tools or anything but it works
This commit is contained in:
		
							
								
								
									
										72
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/bcrypt/bcrypt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/bcrypt/bcrypt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| // Package bcrypt implements the bcrypt password hashing mechanism. | ||||
| // | ||||
| // Please note that bcrypt truncates passwords to 72 characters in length. Consider using | ||||
| // a more modern hashing scheme such as scrypt or sha-crypt. If you must use bcrypt, | ||||
| // consider using bcrypt-sha256 instead. | ||||
| package bcrypt | ||||
|  | ||||
| import "golang.org/x/crypto/bcrypt" | ||||
| import "gopkg.in/hlandau/passlib.v1/abstract" | ||||
| import "fmt" | ||||
|  | ||||
| // An implementation of Scheme implementing bcrypt. | ||||
| // | ||||
| // Uses RecommendedCost. | ||||
| var Crypter abstract.Scheme | ||||
|  | ||||
| // The recommended cost for bcrypt. This may change with subsequent releases. | ||||
| const RecommendedCost = 12 | ||||
|  | ||||
| // bcrypt.DefaultCost is a bit low (10), so use 12 instead. | ||||
|  | ||||
| func init() { | ||||
| 	Crypter = New(RecommendedCost) | ||||
| } | ||||
|  | ||||
| // Create a new scheme implementing bcrypt. The recommended cost is RecommendedCost. | ||||
| func New(cost int) abstract.Scheme { | ||||
| 	return &scheme{ | ||||
| 		Cost: cost, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type scheme struct { | ||||
| 	Cost int | ||||
| } | ||||
|  | ||||
| func (s *scheme) SupportsStub(stub string) bool { | ||||
| 	return len(stub) >= 3 && stub[0] == '$' && stub[1] == '2' && | ||||
| 		(stub[2] == '$' || (len(stub) >= 4 && stub[3] == '$' && | ||||
| 			(stub[2] == 'a' || stub[2] == 'b' || stub[2] == 'y'))) | ||||
| } | ||||
|  | ||||
| func (s *scheme) Hash(password string) (string, error) { | ||||
| 	h, err := bcrypt.GenerateFromPassword([]byte(password), s.Cost) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	return string(h), nil | ||||
| } | ||||
|  | ||||
| func (s *scheme) Verify(password, hash string) error { | ||||
| 	err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) | ||||
| 	if err == bcrypt.ErrMismatchedHashAndPassword { | ||||
| 		err = abstract.ErrInvalidPassword | ||||
| 	} | ||||
|  | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (s *scheme) NeedsUpdate(stub string) bool { | ||||
| 	cost, err := bcrypt.Cost([]byte(stub)) | ||||
| 	if err != nil { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	return cost < s.Cost | ||||
| } | ||||
|  | ||||
| func (s *scheme) String() string { | ||||
| 	return fmt.Sprintf("bcrypt(%d)", s.Cost) | ||||
| } | ||||
							
								
								
									
										96
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/bcryptsha256/bcryptsha256.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/bcryptsha256/bcryptsha256.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| // Package bcryptsha256 implements bcrypt with a SHA256 prehash in a format that is compatible with Python passlib's equivalent bcrypt-sha256 scheme. | ||||
| // | ||||
| // This is preferred over bcrypt because the prehash essentially renders bcrypt's password length | ||||
| // limitation irrelevant; although of course it is less compatible. | ||||
| package bcryptsha256 | ||||
|  | ||||
| import "gopkg.in/hlandau/passlib.v1/abstract" | ||||
| import "gopkg.in/hlandau/passlib.v1/hash/bcrypt" | ||||
| import "encoding/base64" | ||||
| import "crypto/sha256" | ||||
| import "strings" | ||||
| import "fmt" | ||||
|  | ||||
| type scheme struct { | ||||
| 	underlying abstract.Scheme | ||||
| 	cost       int | ||||
| } | ||||
|  | ||||
| // An implementation of Scheme implementing Python passlib's `$bcrypt-sha256$` | ||||
| // bcrypt variant. This is bcrypt with a SHA256 prehash, which removes bcrypt's | ||||
| // password length limitation. | ||||
| var Crypter abstract.Scheme | ||||
|  | ||||
| // The recommended cost for bcrypt-sha256. This may change with subsequent releases. | ||||
| const RecommendedCost = bcrypt.RecommendedCost | ||||
|  | ||||
| func init() { | ||||
| 	Crypter = New(bcrypt.RecommendedCost) | ||||
| } | ||||
|  | ||||
| // Instantiates a new Scheme implementing bcrypt with the given cost. | ||||
| // | ||||
| // The recommended cost is RecommendedCost. | ||||
| func New(cost int) abstract.Scheme { | ||||
| 	return &scheme{ | ||||
| 		underlying: bcrypt.New(cost), | ||||
| 		cost:       cost, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (s *scheme) Hash(password string) (string, error) { | ||||
| 	p := s.prehash(password) | ||||
| 	h, err := s.underlying.Hash(p) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	return mangle(h), nil | ||||
| } | ||||
|  | ||||
| func (s *scheme) Verify(password, hash string) error { | ||||
| 	p := s.prehash(password) | ||||
| 	return s.underlying.Verify(p, demangle(hash)) | ||||
| } | ||||
|  | ||||
| func (s *scheme) prehash(password string) string { | ||||
| 	h := sha256.New() | ||||
| 	h.Write([]byte(password)) | ||||
| 	v := base64.StdEncoding.EncodeToString(h.Sum(nil)) | ||||
| 	return v | ||||
| } | ||||
|  | ||||
| func (s *scheme) SupportsStub(stub string) bool { | ||||
| 	return strings.HasPrefix(stub, "$bcrypt-sha256$") && s.underlying.SupportsStub(demangle(stub)) | ||||
| } | ||||
|  | ||||
| func (s *scheme) NeedsUpdate(stub string) bool { | ||||
| 	return s.underlying.NeedsUpdate(demangle(stub)) | ||||
| } | ||||
|  | ||||
| func (s *scheme) String() string { | ||||
| 	return fmt.Sprintf("bcrypt-sha256(%d)", s.cost) | ||||
| } | ||||
|  | ||||
| func demangle(stub string) string { | ||||
| 	if strings.HasPrefix(stub, "$bcrypt-sha256$2") { | ||||
| 		parts := strings.Split(stub[15:], "$") | ||||
| 		// 0: 2a,12 | ||||
| 		// 1: salt | ||||
| 		// 2: hash | ||||
| 		parts0 := strings.Split(parts[0], ",") | ||||
| 		return "$" + parts0[0] + "$" + fmt.Sprintf("%02s", parts0[1]) + "$" + parts[1] + parts[2] | ||||
| 	} else { | ||||
| 		return stub | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func mangle(hash string) string { | ||||
| 	parts := strings.Split(hash[1:], "$") | ||||
| 	// 0: 2a | ||||
| 	// 1: rounds | ||||
| 	// 2: salt + hash | ||||
| 	salt := parts[2][0:22] | ||||
| 	h := parts[2][22:] | ||||
| 	return "$bcrypt-sha256$" + parts[0] + "," + parts[1] + "$" + salt + "$" + h | ||||
| } | ||||
							
								
								
									
										95
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/scrypt/raw/scrypt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/scrypt/raw/scrypt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| // Package raw provides a raw implementation of the modular-crypt-wrapped scrypt primitive. | ||||
| package raw | ||||
|  | ||||
| import "golang.org/x/crypto/scrypt" | ||||
| import "encoding/base64" | ||||
| import "strings" | ||||
| import "strconv" | ||||
| import "fmt" | ||||
|  | ||||
| // The current recommended N value for interactive logins. | ||||
| const RecommendedN = 16384 | ||||
|  | ||||
| // The current recommended r value for interactive logins. | ||||
| const Recommendedr = 8 | ||||
|  | ||||
| // The current recommended p value for interactive logins. | ||||
| const Recommendedp = 1 | ||||
|  | ||||
| // Wrapper for golang.org/x/crypto/scrypt implementing a sensible | ||||
| // modular crypt interface. | ||||
| // | ||||
| // password should be a UTF-8 plaintext password. | ||||
| // salt should be a random salt value in binary form. | ||||
| // | ||||
| // N, r and p are parameters to scrypt. | ||||
| // | ||||
| // Returns a modular crypt hash. | ||||
| func ScryptSHA256(password string, salt []byte, N, r, p int) string { | ||||
| 	passwordb := []byte(password) | ||||
|  | ||||
| 	hash, err := scrypt.Key(passwordb, salt, N, r, p, 32) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
|  | ||||
| 	hstr := base64.StdEncoding.EncodeToString(hash) | ||||
| 	sstr := base64.StdEncoding.EncodeToString(salt) | ||||
|  | ||||
| 	return fmt.Sprintf("$s2$%d$%d$%d$%s$%s", N, r, p, sstr, hstr) | ||||
| } | ||||
|  | ||||
| // Indicates that a password hash or stub is invalid. | ||||
| var ErrInvalidStub = fmt.Errorf("invalid scrypt password stub") | ||||
|  | ||||
| // Parses an scrypt modular hash or stub string. | ||||
| // | ||||
| // The format is as follows: | ||||
| // | ||||
| //   $s2$N$r$p$salt$hash    // hash | ||||
| //   $s2$N$r$p$salt         // stub | ||||
| // | ||||
| func Parse(stub string) (salt, hash []byte, N, r, p int, err error) { | ||||
| 	if len(stub) < 10 || !strings.HasPrefix(stub, "$s2$") { | ||||
| 		err = ErrInvalidStub | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// $s2$  N$r$p$salt-base64$hash-base64 | ||||
| 	parts := strings.Split(stub[4:], "$") | ||||
|  | ||||
| 	if len(parts) < 4 { | ||||
| 		err = ErrInvalidStub | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	var Ni, ri, pi uint64 | ||||
|  | ||||
| 	Ni, err = strconv.ParseUint(parts[0], 10, 31) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	ri, err = strconv.ParseUint(parts[1], 10, 31) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	pi, err = strconv.ParseUint(parts[2], 10, 31) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	N, r, p = int(Ni), int(ri), int(pi) | ||||
|  | ||||
| 	salt, err = base64.StdEncoding.DecodeString(parts[3]) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if len(parts) >= 5 { | ||||
| 		hash, err = base64.StdEncoding.DecodeString(parts[4]) | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										113
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/scrypt/scrypt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/scrypt/scrypt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,113 @@ | ||||
| // Package scrypt implements the scrypt password hashing mechanism, wrapped in | ||||
| // the modular crypt format. | ||||
| package scrypt | ||||
|  | ||||
| import "fmt" | ||||
| import "expvar" | ||||
| import "strings" | ||||
| import "crypto/rand" | ||||
| import "encoding/base64" | ||||
| import "gopkg.in/hlandau/passlib.v1/hash/scrypt/raw" | ||||
| import "gopkg.in/hlandau/passlib.v1/abstract" | ||||
|  | ||||
| var cScryptSHA256HashCalls = expvar.NewInt("passlib.scryptsha256.hashCalls") | ||||
| var cScryptSHA256VerifyCalls = expvar.NewInt("passlib.scryptsha256.verifyCalls") | ||||
|  | ||||
| // An implementation of Scheme performing scrypt-sha256. | ||||
| // | ||||
| // Uses the recommended values for N,r,p defined in raw. | ||||
| var SHA256Crypter abstract.Scheme | ||||
|  | ||||
| func init() { | ||||
| 	SHA256Crypter = NewSHA256( | ||||
| 		raw.RecommendedN, | ||||
| 		raw.Recommendedr, | ||||
| 		raw.Recommendedp, | ||||
| 	) | ||||
| } | ||||
|  | ||||
| // Returns an implementation of Scheme implementing scrypt-sha256 | ||||
| // with the specified parameters. | ||||
| func NewSHA256(N, r, p int) abstract.Scheme { | ||||
| 	return &scryptSHA256Crypter{ | ||||
| 		nN: N, | ||||
| 		r:  r, | ||||
| 		p:  p, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type scryptSHA256Crypter struct { | ||||
| 	nN, r, p int | ||||
| } | ||||
|  | ||||
| func (c *scryptSHA256Crypter) SetParams(N, r, p int) error { | ||||
| 	c.nN = N | ||||
| 	c.r = r | ||||
| 	c.p = p | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (c *scryptSHA256Crypter) SupportsStub(stub string) bool { | ||||
| 	return strings.HasPrefix(stub, "$s2$") | ||||
| } | ||||
|  | ||||
| func (c *scryptSHA256Crypter) Hash(password string) (string, error) { | ||||
| 	cScryptSHA256HashCalls.Add(1) | ||||
|  | ||||
| 	stub, err := c.makeStub() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	_, newHash, _, _, _, _, err := c.hash(password, stub) | ||||
| 	return newHash, err | ||||
| } | ||||
|  | ||||
| func (c *scryptSHA256Crypter) Verify(password, hash string) (err error) { | ||||
| 	cScryptSHA256VerifyCalls.Add(1) | ||||
|  | ||||
| 	_, newHash, _, _, _, _, err := c.hash(password, hash) | ||||
| 	if err == nil && !abstract.SecureCompare(hash, newHash) { | ||||
| 		err = abstract.ErrInvalidPassword | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (c *scryptSHA256Crypter) NeedsUpdate(stub string) bool { | ||||
| 	salt, _, N, r, p, err := raw.Parse(stub) | ||||
| 	if err != nil { | ||||
| 		return false // ... | ||||
| 	} | ||||
|  | ||||
| 	return c.needsUpdate(salt, N, r, p) | ||||
| } | ||||
|  | ||||
| func (c *scryptSHA256Crypter) needsUpdate(salt []byte, N, r, p int) bool { | ||||
| 	return len(salt) < 18 || N < c.nN || r < c.r || p < c.p | ||||
| } | ||||
|  | ||||
| func (c *scryptSHA256Crypter) hash(password, stub string) (oldHashRaw []byte, newHash string, salt []byte, N, r, p int, err error) { | ||||
| 	salt, oldHashRaw, N, r, p, err = raw.Parse(stub) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	return oldHashRaw, raw.ScryptSHA256(password, salt, N, r, p), salt, N, r, p, nil | ||||
| } | ||||
|  | ||||
| func (c *scryptSHA256Crypter) makeStub() (string, error) { | ||||
| 	buf := make([]byte, 18) | ||||
| 	_, err := rand.Read(buf) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	salt := base64.StdEncoding.EncodeToString(buf) | ||||
|  | ||||
| 	return fmt.Sprintf("$s2$%d$%d$%d$%s", c.nN, c.r, c.p, salt), nil | ||||
| } | ||||
|  | ||||
| func (c *scryptSHA256Crypter) String() string { | ||||
| 	return fmt.Sprintf("scrypt-sha256(%d,%d,%d)", c.nN, c.r, c.p) | ||||
| } | ||||
							
								
								
									
										34
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/sha2crypt/raw/base64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/sha2crypt/raw/base64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| package raw | ||||
|  | ||||
| const bmap = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" | ||||
|  | ||||
| // Encodes a byte string using the sha2-crypt base64 variant. | ||||
| func EncodeBase64(b []byte) string { | ||||
| 	o := make([]byte, len(b)/3*4+4) | ||||
|  | ||||
| 	for i, j := 0, 0; i < len(b); { | ||||
| 		b1 := b[i] | ||||
| 		b2 := byte(0) | ||||
| 		b3 := byte(0) | ||||
|  | ||||
| 		if (i + 1) < len(b) { | ||||
| 			b2 = b[i+1] | ||||
| 		} | ||||
| 		if (i + 2) < len(b) { | ||||
| 			b3 = b[i+2] | ||||
| 		} | ||||
|  | ||||
| 		o[j] = bmap[(b1 & 0x3F)] | ||||
| 		o[j+1] = bmap[((b1&0xC0)>>6)|((b2&0x0F)<<2)] | ||||
| 		o[j+2] = bmap[((b2&0xF0)>>4)|((b3&0x03)<<4)] | ||||
| 		o[j+3] = bmap[(b3&0xFC)>>2] | ||||
| 		i += 3 | ||||
| 		j += 4 | ||||
| 	} | ||||
|  | ||||
| 	s := string(o) | ||||
| 	return s[0 : len(b)*4/3-(len(b)%4)+1] | ||||
| } | ||||
|  | ||||
| // © 2008-2012 Assurance Technologies LLC.  (Python passlib)  BSD License | ||||
| // © 2014 Hugo Landau <hlandau@devever.net>  BSD License | ||||
							
								
								
									
										82
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/sha2crypt/raw/parse.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/sha2crypt/raw/parse.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| package raw | ||||
|  | ||||
| import "fmt" | ||||
| import "strings" | ||||
| import "strconv" | ||||
|  | ||||
| // Indicates that a password hash or stub is invalid. | ||||
| var ErrInvalidStub = fmt.Errorf("invalid stub") | ||||
|  | ||||
| // Indicates that the number of rounds specified is not in the valid range. | ||||
| var ErrInvalidRounds = fmt.Errorf("invalid number of rounds") | ||||
|  | ||||
| // Scans a sha256-crypt or sha512-crypt modular crypt stub or modular crypt hash | ||||
| // to determine configuration parameters. | ||||
| func Parse(stub string) (isSHA512 bool, salt, hash string, rounds int, err error) { | ||||
| 	// $5$ | ||||
| 	if len(stub) < 3 || stub[0] != '$' || stub[2] != '$' { | ||||
| 		err = ErrInvalidStub | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if stub[1] == '6' { | ||||
| 		isSHA512 = true | ||||
| 	} else if stub[1] != '5' { | ||||
| 		err = ErrInvalidStub | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	rest := stub[3:] | ||||
| 	parts := strings.Split(rest, "$") | ||||
| 	roundsStr := "" | ||||
|  | ||||
| 	switch len(parts) { | ||||
| 	case 1: | ||||
| 		// $5$ | ||||
| 		// $5$salt | ||||
| 		salt = parts[0] | ||||
| 	case 2: | ||||
| 		// $5$salt$hash | ||||
| 		// $5$rounds=1000$salt | ||||
| 		if strings.HasPrefix(parts[0], "rounds=") { | ||||
| 			roundsStr = parts[0] | ||||
| 			salt = parts[1] | ||||
| 		} else { | ||||
| 			salt = parts[0] | ||||
| 			hash = parts[1] | ||||
| 		} | ||||
| 	case 3: | ||||
| 		// $5$rounds=1000$salt$hash | ||||
| 		roundsStr = parts[0] | ||||
| 		salt = parts[1] | ||||
| 		hash = parts[2] | ||||
| 	default: | ||||
| 		err = ErrInvalidStub | ||||
| 	} | ||||
|  | ||||
| 	if roundsStr != "" { | ||||
| 		if !strings.HasPrefix(roundsStr, "rounds=") { | ||||
| 			err = ErrInvalidStub | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		roundsStr = roundsStr[7:] | ||||
| 		var n uint64 | ||||
| 		n, err = strconv.ParseUint(roundsStr, 10, 31) | ||||
| 		if err != nil { | ||||
| 			err = ErrInvalidStub | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		rounds = int(n) | ||||
|  | ||||
| 		if rounds < MinimumRounds || rounds > MaximumRounds { | ||||
| 			err = ErrInvalidRounds | ||||
| 			return | ||||
| 		} | ||||
| 	} else { | ||||
| 		rounds = DefaultRounds | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										187
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/sha2crypt/raw/sha2crypt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/sha2crypt/raw/sha2crypt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,187 @@ | ||||
| // Package raw provides a raw implementation of the sha256-crypt and sha512-crypt primitives. | ||||
| package raw | ||||
|  | ||||
| import "io" | ||||
| import "fmt" | ||||
| import "hash" | ||||
| import "crypto/sha256" | ||||
| import "crypto/sha512" | ||||
|  | ||||
| // The minimum number of rounds permissible for sha256-crypt and sha512-crypt. | ||||
| const MinimumRounds = 1000 | ||||
|  | ||||
| // The maximum number of rounds permissible for sha256-crypt and sha512-crypt. | ||||
| // Don't use this! | ||||
| const MaximumRounds = 999999999 | ||||
|  | ||||
| // This is the 'default' number of rounds for sha256-crypt and sha512-crypt. If | ||||
| // this rounds value is used the number of rounds is not explicitly specified | ||||
| // in the modular crypt format, as it is the default. | ||||
| const DefaultRounds = 5000 | ||||
|  | ||||
| // This is the recommended number of rounds for sha256-crypt and sha512-crypt. | ||||
| // This may change with subsequent releases of this package. It is recommended | ||||
| // that you invoke sha256-crypt or sha512-crypt with this value, or a value | ||||
| // proportional to it. | ||||
| const RecommendedRounds = 10000 | ||||
|  | ||||
| // Calculates sha256-crypt. The password must be in plaintext and be a UTF-8 | ||||
| // string. | ||||
| // | ||||
| // The salt must be a valid ASCII between 0 and 16 characters in length | ||||
| // inclusive. | ||||
| // | ||||
| // See the constants in this package for suggested values for rounds. | ||||
| // | ||||
| // Rounds must be in the range 1000 <= rounds <= 999999999. The function panics | ||||
| // if this is not the case. | ||||
| // | ||||
| // The output is in modular crypt format. | ||||
| func Crypt256(password, salt string, rounds int) string { | ||||
| 	return "$5" + shaCrypt(password, salt, rounds, sha256.New, transpose256) | ||||
| } | ||||
|  | ||||
| // Calculates sha256-crypt. The password must be in plaintext and be a UTF-8 | ||||
| // string. | ||||
| // | ||||
| // The salt must be a valid ASCII between 0 and 16 characters in length | ||||
| // inclusive. | ||||
| // | ||||
| // See the constants in this package for suggested values for rounds. | ||||
| // | ||||
| // Rounds must be in the range 1000 <= rounds <= 999999999. The function panics | ||||
| // if this is not the case. | ||||
| // | ||||
| // The output is in modular crypt format. | ||||
| func Crypt512(password, salt string, rounds int) string { | ||||
| 	return "$6" + shaCrypt(password, salt, rounds, sha512.New, transpose512) | ||||
| } | ||||
|  | ||||
| func shaCrypt(password, salt string, rounds int, newHash func() hash.Hash, transpose func(b []byte)) string { | ||||
| 	if rounds < MinimumRounds || rounds > MaximumRounds { | ||||
| 		panic("sha256-crypt rounds must be in 1000 <= rounds <= 999999999") | ||||
| 	} | ||||
|  | ||||
| 	passwordb := []byte(password) | ||||
| 	saltb := []byte(salt) | ||||
| 	if len(saltb) > 16 { | ||||
| 		panic("salt must not exceed 16 bytes") | ||||
| 	} | ||||
|  | ||||
| 	// B | ||||
| 	b := newHash() | ||||
| 	b.Write(passwordb) | ||||
| 	b.Write(saltb) | ||||
| 	b.Write(passwordb) | ||||
| 	bsum := b.Sum(nil) | ||||
|  | ||||
| 	// A | ||||
| 	a := newHash() | ||||
| 	a.Write(passwordb) | ||||
| 	a.Write(saltb) | ||||
| 	repeat(a, bsum, len(passwordb)) | ||||
|  | ||||
| 	plen := len(passwordb) | ||||
| 	for plen != 0 { | ||||
| 		if (plen & 1) != 0 { | ||||
| 			a.Write(bsum) | ||||
| 		} else { | ||||
| 			a.Write(passwordb) | ||||
| 		} | ||||
| 		plen = plen >> 1 | ||||
| 	} | ||||
|  | ||||
| 	asum := a.Sum(nil) | ||||
|  | ||||
| 	// DP | ||||
| 	dp := newHash() | ||||
| 	for i := 0; i < len(passwordb); i++ { | ||||
| 		dp.Write(passwordb) | ||||
| 	} | ||||
|  | ||||
| 	dpsum := dp.Sum(nil) | ||||
|  | ||||
| 	// P | ||||
| 	p := make([]byte, len(passwordb)) | ||||
| 	repeatTo(p, dpsum) | ||||
|  | ||||
| 	// DS | ||||
| 	ds := newHash() | ||||
| 	for i := 0; i < (16 + int(asum[0])); i++ { | ||||
| 		ds.Write(saltb) | ||||
| 	} | ||||
|  | ||||
| 	dssum := ds.Sum(nil)[0:len(saltb)] | ||||
|  | ||||
| 	// S | ||||
| 	s := make([]byte, len(saltb)) | ||||
| 	repeatTo(s, dssum) | ||||
|  | ||||
| 	// C | ||||
| 	cur := asum[:] | ||||
| 	for i := 0; i < rounds; i++ { | ||||
| 		c := newHash() | ||||
| 		if (i & 1) != 0 { | ||||
| 			c.Write(p) | ||||
| 		} else { | ||||
| 			c.Write(cur) | ||||
| 		} | ||||
| 		if (i % 3) != 0 { | ||||
| 			c.Write(s) | ||||
| 		} | ||||
| 		if (i % 7) != 0 { | ||||
| 			c.Write(p) | ||||
| 		} | ||||
| 		if (i & 1) == 0 { | ||||
| 			c.Write(p) | ||||
| 		} else { | ||||
| 			c.Write(cur) | ||||
| 		} | ||||
| 		cur = c.Sum(nil)[:] | ||||
| 	} | ||||
|  | ||||
| 	// Transposition | ||||
| 	transpose(cur) | ||||
|  | ||||
| 	// Hash | ||||
| 	hstr := EncodeBase64(cur) | ||||
|  | ||||
| 	if rounds == DefaultRounds { | ||||
| 		return fmt.Sprintf("$%s$%s", salt, hstr) | ||||
| 	} | ||||
|  | ||||
| 	return fmt.Sprintf("$rounds=%d$%s$%s", rounds, salt, hstr) | ||||
| } | ||||
|  | ||||
| func repeat(w io.Writer, b []byte, sz int) { | ||||
| 	var i int | ||||
| 	for i = 0; (i + len(b)) <= sz; i += len(b) { | ||||
| 		w.Write(b) | ||||
| 	} | ||||
| 	w.Write(b[0 : sz-i]) | ||||
| } | ||||
|  | ||||
| func repeatTo(out []byte, b []byte) { | ||||
| 	if len(b) == 0 { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	var i int | ||||
| 	for i = 0; (i + len(b)) <= len(out); i += len(b) { | ||||
| 		copy(out[i:], b) | ||||
| 	} | ||||
| 	copy(out[i:], b) | ||||
| } | ||||
|  | ||||
| func transpose256(b []byte) { | ||||
| 	b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19], b[20], b[21], b[22], b[23], b[24], b[25], b[26], b[27], b[28], b[29], b[30], b[31] = | ||||
| 		b[20], b[10], b[0], b[11], b[1], b[21], b[2], b[22], b[12], b[23], b[13], b[3], b[14], b[4], b[24], b[5], b[25], b[15], b[26], b[16], b[6], b[17], b[7], b[27], b[8], b[28], b[18], b[29], b[19], b[9], b[30], b[31] | ||||
| } | ||||
|  | ||||
| func transpose512(b []byte) { | ||||
| 	b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19], b[20], b[21], b[22], b[23], b[24], b[25], b[26], b[27], b[28], b[29], b[30], b[31], b[32], b[33], b[34], b[35], b[36], b[37], b[38], b[39], b[40], b[41], b[42], b[43], b[44], b[45], b[46], b[47], b[48], b[49], b[50], b[51], b[52], b[53], b[54], b[55], b[56], b[57], b[58], b[59], b[60], b[61], b[62], b[63] = | ||||
| 		b[42], b[21], b[0], b[1], b[43], b[22], b[23], b[2], b[44], b[45], b[24], b[3], b[4], b[46], b[25], b[26], b[5], b[47], b[48], b[27], b[6], b[7], b[49], b[28], b[29], b[8], b[50], b[51], b[30], b[9], b[10], b[52], b[31], b[32], b[11], b[53], b[54], b[33], b[12], b[13], b[55], b[34], b[35], b[14], b[56], b[57], b[36], b[15], b[16], b[58], b[37], b[38], b[17], b[59], b[60], b[39], b[18], b[19], b[61], b[40], b[41], b[20], b[62], b[63] | ||||
| } | ||||
|  | ||||
| // © 2008-2012 Assurance Technologies LLC.  (Python passlib)  BSD License | ||||
| // © 2014 Hugo Landau <hlandau@devever.net>  BSD License | ||||
							
								
								
									
										147
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/sha2crypt/sha2crypt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								vendor/gopkg.in/hlandau/passlib.v1/hash/sha2crypt/sha2crypt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,147 @@ | ||||
| // Package sha2crypt implements sha256-crypt and sha512-crypt. | ||||
| package sha2crypt | ||||
|  | ||||
| import "fmt" | ||||
| import "expvar" | ||||
| import "crypto/rand" | ||||
| import "gopkg.in/hlandau/passlib.v1/hash/sha2crypt/raw" | ||||
| import "gopkg.in/hlandau/passlib.v1/abstract" | ||||
|  | ||||
| var cSHA2CryptHashCalls = expvar.NewInt("passlib.sha2crypt.hashCalls") | ||||
| var cSHA2CryptVerifyCalls = expvar.NewInt("passlib.sha2crypt.verifyCalls") | ||||
|  | ||||
| // An implementation of Scheme performing sha256-crypt. | ||||
| // | ||||
| // The number of rounds is raw.RecommendedRounds. | ||||
| var Crypter256 abstract.Scheme | ||||
|  | ||||
| // An implementation of Scheme performing sha512-crypt. | ||||
| // | ||||
| // The number of rounds is raw.RecommendedRounds. | ||||
| var Crypter512 abstract.Scheme | ||||
|  | ||||
| func init() { | ||||
| 	Crypter256 = NewCrypter256(raw.RecommendedRounds) | ||||
| 	Crypter512 = NewCrypter512(raw.RecommendedRounds) | ||||
| } | ||||
|  | ||||
| // Returns a Scheme implementing sha256-crypt using the number of rounds | ||||
| // specified. | ||||
| func NewCrypter256(rounds int) abstract.Scheme { | ||||
| 	return &sha2Crypter{false, rounds} | ||||
| } | ||||
|  | ||||
| // Returns a Scheme implementing sha512-crypt using the number of rounds | ||||
| // specified. | ||||
| func NewCrypter512(rounds int) abstract.Scheme { | ||||
| 	return &sha2Crypter{true, rounds} | ||||
| } | ||||
|  | ||||
| type sha2Crypter struct { | ||||
| 	sha512 bool | ||||
| 	rounds int | ||||
| } | ||||
|  | ||||
| // Changes the default rounds for the crypter. Be warned that this | ||||
| // is a global setting. The default default value is RecommendedRounds. | ||||
| func (c *sha2Crypter) SetRounds(rounds int) error { | ||||
| 	if rounds < raw.MinimumRounds || rounds > raw.MaximumRounds { | ||||
| 		return raw.ErrInvalidRounds | ||||
| 	} | ||||
|  | ||||
| 	c.rounds = rounds | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (c *sha2Crypter) SupportsStub(stub string) bool { | ||||
| 	if len(stub) < 3 || stub[0] != '$' || stub[2] != '$' { | ||||
| 		return false | ||||
| 	} | ||||
| 	return (stub[1] == '5' && !c.sha512) || (stub[1] == '6' && c.sha512) | ||||
| } | ||||
|  | ||||
| func (c *sha2Crypter) Hash(password string) (string, error) { | ||||
| 	cSHA2CryptHashCalls.Add(1) | ||||
|  | ||||
| 	stub, err := c.makeStub() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	_, newHash, _, _, err := c.hash(password, stub) | ||||
| 	return newHash, err | ||||
| } | ||||
|  | ||||
| func (c *sha2Crypter) Verify(password, hash string) (err error) { | ||||
| 	cSHA2CryptVerifyCalls.Add(1) | ||||
|  | ||||
| 	_, newHash, _, _, err := c.hash(password, hash) | ||||
| 	if err == nil && !abstract.SecureCompare(hash, newHash) { | ||||
| 		err = abstract.ErrInvalidPassword | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (c *sha2Crypter) NeedsUpdate(stub string) bool { | ||||
| 	_, salt, _, rounds, err := raw.Parse(stub) | ||||
| 	if err != nil { | ||||
| 		return false // ... | ||||
| 	} | ||||
|  | ||||
| 	return c.needsUpdate(salt, rounds) | ||||
| } | ||||
|  | ||||
| func (c *sha2Crypter) needsUpdate(salt string, rounds int) bool { | ||||
| 	return rounds < c.rounds || len(salt) < 16 | ||||
| } | ||||
|  | ||||
| var errInvalidStub = fmt.Errorf("invalid sha2 password stub") | ||||
|  | ||||
| func (c *sha2Crypter) hash(password, stub string) (oldHash, newHash, salt string, rounds int, err error) { | ||||
| 	isSHA512, salt, oldHash, rounds, err := raw.Parse(stub) | ||||
| 	if err != nil { | ||||
| 		return "", "", "", 0, err | ||||
| 	} | ||||
|  | ||||
| 	if isSHA512 != c.sha512 { | ||||
| 		return "", "", "", 0, errInvalidStub | ||||
| 	} | ||||
|  | ||||
| 	if c.sha512 { | ||||
| 		return oldHash, raw.Crypt512(password, salt, rounds), salt, rounds, nil | ||||
| 	} | ||||
|  | ||||
| 	return oldHash, raw.Crypt256(password, salt, rounds), salt, rounds, nil | ||||
| } | ||||
|  | ||||
| func (c *sha2Crypter) makeStub() (string, error) { | ||||
| 	ch := "5" | ||||
| 	if c.sha512 { | ||||
| 		ch = "6" | ||||
| 	} | ||||
|  | ||||
| 	buf := make([]byte, 12) | ||||
| 	_, err := rand.Read(buf) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	salt := raw.EncodeBase64(buf)[0:16] | ||||
|  | ||||
| 	if c.rounds == raw.DefaultRounds { | ||||
| 		return fmt.Sprintf("$%s$%s", ch, salt), nil | ||||
| 	} | ||||
|  | ||||
| 	return fmt.Sprintf("$%s$rounds=%d$%s", ch, c.rounds, salt), nil | ||||
| } | ||||
|  | ||||
| func (c *sha2Crypter) String() string { | ||||
| 	if c.sha512 { | ||||
| 		return fmt.Sprintf("sha512-crypt(%d)", c.rounds) | ||||
| 	} else { | ||||
| 		return fmt.Sprintf("sha256-crypt(%d)", c.rounds) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // © 2014 Hugo Landau <hlandau@devever.net>  BSD License | ||||
		Reference in New Issue
	
	Block a user