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:
		
							
								
								
									
										97
									
								
								vendor/gopkg.in/hlandau/easymetric.v1/cexp/cexp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								vendor/gopkg.in/hlandau/easymetric.v1/cexp/cexp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| package cexp | ||||
|  | ||||
| import "gopkg.in/hlandau/measurable.v1" | ||||
| import "sync/atomic" | ||||
|  | ||||
| // Counter | ||||
|  | ||||
| type Counter struct { | ||||
| 	name  string | ||||
| 	value int64 | ||||
| } | ||||
|  | ||||
| func (c *Counter) MsName() string { | ||||
| 	return c.name | ||||
| } | ||||
|  | ||||
| func (c *Counter) MsInt64() int64 { | ||||
| 	return atomic.LoadInt64(&c.value) | ||||
| } | ||||
|  | ||||
| func (c *Counter) Get() int64 { | ||||
| 	return c.MsInt64() | ||||
| } | ||||
|  | ||||
| // v must be non-negative. | ||||
| func (c *Counter) Add(v int64) { | ||||
| 	atomic.AddInt64(&c.value, v) | ||||
| } | ||||
|  | ||||
| func (c *Counter) Inc() { | ||||
| 	c.Add(1) | ||||
| } | ||||
|  | ||||
| func (c *Counter) MsType() measurable.Type { | ||||
| 	return measurable.CounterType | ||||
| } | ||||
|  | ||||
| func NewCounter(name string) *Counter { | ||||
| 	c := &Counter{ | ||||
| 		name: name, | ||||
| 	} | ||||
|  | ||||
| 	measurable.Register(c) | ||||
| 	return c | ||||
| } | ||||
|  | ||||
| // Gauge | ||||
|  | ||||
| type Gauge struct { | ||||
| 	name  string | ||||
| 	value int64 | ||||
| } | ||||
|  | ||||
| func (c *Gauge) MsName() string { | ||||
| 	return c.name | ||||
| } | ||||
|  | ||||
| func (c *Gauge) MsInt64() int64 { | ||||
| 	return atomic.LoadInt64(&c.value) | ||||
| } | ||||
|  | ||||
| func (c *Gauge) Add(v int64) { | ||||
| 	atomic.AddInt64(&c.value, v) | ||||
| } | ||||
|  | ||||
| func (c *Gauge) Sub(v int64) { | ||||
| 	c.Add(-v) | ||||
| } | ||||
|  | ||||
| func (c *Gauge) Set(v int64) { | ||||
| 	atomic.StoreInt64(&c.value, v) | ||||
| } | ||||
|  | ||||
| func (c *Gauge) Get() int64 { | ||||
| 	return c.MsInt64() | ||||
| } | ||||
|  | ||||
| func (c *Gauge) Inc() { | ||||
| 	c.Add(1) | ||||
| } | ||||
|  | ||||
| func (c *Gauge) Dec() { | ||||
| 	c.Add(-1) | ||||
| } | ||||
|  | ||||
| func (c *Gauge) MsType() measurable.Type { | ||||
| 	return measurable.GaugeType | ||||
| } | ||||
|  | ||||
| func NewGauge(name string) *Gauge { | ||||
| 	c := &Gauge{ | ||||
| 		name: name, | ||||
| 	} | ||||
|  | ||||
| 	measurable.Register(c) | ||||
| 	return c | ||||
| } | ||||
							
								
								
									
										82
									
								
								vendor/gopkg.in/hlandau/measurable.v1/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								vendor/gopkg.in/hlandau/measurable.v1/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| Measurable: The useless Go metric registration package that doesn't do anything | ||||
| =============================================================================== | ||||
|  | ||||
| [](https://godoc.org/gopkg.in/hlandau/measurable.v1) | ||||
|  | ||||
| Measurable is a Go library for managing the registration of metrics such as | ||||
| counters and gauges, no matter how that metric data is eventually consumed. | ||||
|  | ||||
| The most noteworthy feature of measurable is that it doesn't do anything. It | ||||
| contains no functionality for providing metric data to any external service, | ||||
| and it contains no actual metric implementations. | ||||
|  | ||||
| The purpose of measurable is to act as an [integration | ||||
| nexus](https://www.devever.net/~hl/nexuses), essentially a matchmaker between | ||||
| metric sources and metric consumers. This creates the important feature that | ||||
| your application's metrics can be expressed completely independently of *how* | ||||
| those metrics are exported. | ||||
|  | ||||
| Measurable doesn't implement any metric or metric export logic because it | ||||
| strives to be a neutral intermediary, which abstracts the interface between | ||||
| metrics and metric exporters. | ||||
|  | ||||
| **Import as:** `gopkg.in/hlandau/measurable.v1` | ||||
|  | ||||
| Measurable | ||||
| ---------- | ||||
|  | ||||
| A Measurable is an object that represents some metric. It is obliged only to | ||||
| implement the following interface: | ||||
|  | ||||
| ```go | ||||
| type Measurable interface { | ||||
|   MsName() string | ||||
|   MsType() Type | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Measurable is designed around interface upgrades. If you want to actually | ||||
| do anything with a Measurable, you must attempt to cast it to an interface | ||||
| with the methods you need. A Measurable is not obliged to implement any | ||||
| interface besides Measurable, but almost always will. | ||||
|  | ||||
| Here are some common interfaces implemented by Measurables, in descending order | ||||
| of importance: | ||||
|  | ||||
|   - `MsName() string` — get the Measurable name. | ||||
|   - `MsType() Type` — get the Measurable type. | ||||
|   - `MsInt64() int64` — get the Measurable as an int64. | ||||
|   - `String() string` — the standard Go `String()` interface. | ||||
|  | ||||
| All Measurables should implement `MsName() string` and `MsType() Type`. | ||||
|  | ||||
| Measurable-specific methods should always be prefixed by `Ms` so it is clear | ||||
| they are intended for consumption by Measurable consumers. | ||||
|  | ||||
| `MsName`, `MsType` and `MsInt64` should suffice for most consumers of Counter | ||||
| and Gauge metric types. | ||||
|  | ||||
| Metrics should be named in lowercase using dots to create a hierarchy and | ||||
| dashes to separate words, e.g. `someserver.http.request-count`. These metric | ||||
| names may be transmuted by consumers as necessary for some graphing systems, | ||||
| such as Prometheus (which allows only underscores). | ||||
|  | ||||
| Standard Bindings | ||||
| ----------------- | ||||
|  | ||||
| For a package which makes it easy to register and consume measurables, see the | ||||
| [easymetric](https://github.com/hlandau/easymetric) package. | ||||
|  | ||||
| Of course, nothing requires you to use the easymetric package. You are free to escew it and make your own. | ||||
|  | ||||
| Background Reading | ||||
| ------------------ | ||||
|  | ||||
|   - [On Nexuses](https://www.devever.net/~hl/nexuses) | ||||
|   - See also: [Configurable](https://github.com/hlandau/configurable) | ||||
|  | ||||
| Licence | ||||
| ------- | ||||
|  | ||||
|     © 2015 Hugo Landau <hlandau@devever.net>    MIT License | ||||
|  | ||||
							
								
								
									
										189
									
								
								vendor/gopkg.in/hlandau/measurable.v1/measurable.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										189
									
								
								vendor/gopkg.in/hlandau/measurable.v1/measurable.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,189 @@ | ||||
| // Package measurable provides a functionality-free integration nexus for | ||||
| // metric registration. | ||||
| // | ||||
| // Measurable is a Go package for connecting service metrics and metric consumers. | ||||
| // | ||||
| // The most noteworthy feature of measurable is that it doesn't do anything. | ||||
| // It contains no functionality for defining or exporting metrics. | ||||
| // | ||||
| // The purpose of measurable is to act as an integration nexus | ||||
| // (https://www.devever.net/~hl/nexuses), essentially a matchmaker between | ||||
| // application metrics and metric consumers. This creates the important feature | ||||
| // that your application's metrics can be defined completely independently of | ||||
| // *how* those metrics are defined. | ||||
| // | ||||
| // Measurable doesn't implement any metric definition or export logic because it | ||||
| // strives to be a neutral intermediary, which abstracts the interface between | ||||
| // measurables and measurable consumers | ||||
| // | ||||
| // Pursuant to this, package measurable is this and only this: an interface | ||||
| // Measurable which all metrics must implement, and a facility for registering | ||||
| // Measurables and visiting them. | ||||
| package measurable // import "gopkg.in/hlandau/measurable.v1" | ||||
|  | ||||
| import "sync" | ||||
| import "fmt" | ||||
|  | ||||
| // Measurable is the interface which must be implemented by any metric item to | ||||
| // be used with package measurable. In the current version, v1, it contains | ||||
| // only the MsName() and MsType() methods. All other functionality must be | ||||
| // obtained by interface upgrades. | ||||
| type Measurable interface { | ||||
| 	// Returns the name of the metric. Names should be in the style | ||||
| 	// "alpha.beta.gamma-delta", for example "foo.http.requests.count". That is, | ||||
| 	// names should be lowercase, should express a hierarchy separated by dots, | ||||
| 	// and have words separated by dashes. | ||||
| 	// | ||||
| 	// Some Measurable consumers may mutate these names to satisfy naming | ||||
| 	// restrictions applied by some graphing systems. | ||||
| 	MsName() string | ||||
|  | ||||
| 	// Return the Measurable type. You can, of course, invent your own Measurable | ||||
| 	// types, though consumers won't necessarily know what to do with them. | ||||
| 	MsType() Type | ||||
| } | ||||
|  | ||||
| var measurablesMutex sync.RWMutex | ||||
| var measurables = map[string]Measurable{} | ||||
|  | ||||
| // Registers a top-level Configurable. | ||||
| func Register(measurable Measurable) { | ||||
| 	measurablesMutex.Lock() | ||||
| 	defer measurablesMutex.Unlock() | ||||
|  | ||||
| 	if measurable == nil { | ||||
| 		panic("cannot register nil measurable") | ||||
| 	} | ||||
|  | ||||
| 	name := measurable.MsName() | ||||
| 	if name == "" { | ||||
| 		panic("measurable cannot have empty name") | ||||
| 	} | ||||
|  | ||||
| 	_, exists := measurables[name] | ||||
| 	if exists { | ||||
| 		panic(fmt.Sprintf("A measurable with the same name already exists: %s", name)) | ||||
| 	} | ||||
|  | ||||
| 	measurables[name] = measurable | ||||
| 	callRegistrationHooks(measurable, RegisterEvent) | ||||
| } | ||||
|  | ||||
| func Unregister(measurableName string) { | ||||
| 	measurablesMutex.Lock() | ||||
| 	defer measurablesMutex.Unlock() | ||||
|  | ||||
| 	measurable, ok := measurables[measurableName] | ||||
| 	if !ok { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	callRegistrationHooks(measurable, UnregisterEvent) | ||||
| 	delete(measurables, measurableName) | ||||
| } | ||||
|  | ||||
| func Get(measurableName string) Measurable { | ||||
| 	measurablesMutex.RLock() | ||||
| 	defer measurablesMutex.RUnlock() | ||||
|  | ||||
| 	return measurables[measurableName] | ||||
| } | ||||
|  | ||||
| // Visits all registered top-level Measurables. | ||||
| // | ||||
| // Returning a non-nil error short-circuits the iteration process and returns | ||||
| // that error. | ||||
| func Visit(do func(measurable Measurable) error) error { | ||||
| 	measurablesMutex.Lock() | ||||
| 	defer measurablesMutex.Unlock() | ||||
|  | ||||
| 	for _, measurable := range measurables { | ||||
| 		err := do(measurable) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Represents a measurable type. | ||||
| type Type uint32 | ||||
|  | ||||
| const ( | ||||
| 	// A CounterType Measurable represents a non-negative integral value | ||||
| 	// that monotonously increases. It must implement `MsInt64() int64`. | ||||
| 	CounterType Type = 0x436E7472 | ||||
|  | ||||
| 	// A GaugeType Measurable represents an integral value that varies over | ||||
| 	// time. It must implement `MsInt64() int64`. | ||||
| 	GaugeType = 0x47617567 | ||||
| ) | ||||
|  | ||||
| // Registration hooks. | ||||
| type HookEvent int | ||||
|  | ||||
| const ( | ||||
| 	// This event is issued when a measurable is registered. | ||||
| 	RegisterEvent HookEvent = iota | ||||
|  | ||||
| 	// This event is issued when a registration hook is registered. It is issued | ||||
| 	// for every measurable which has already been registered. | ||||
| 	RegisterCatchupEvent | ||||
|  | ||||
| 	// This event is issued when a measurable is unregistered. | ||||
| 	UnregisterEvent | ||||
| ) | ||||
|  | ||||
| type HookFunc func(measurable Measurable, hookEvent HookEvent) | ||||
|  | ||||
| var hooksMutex sync.RWMutex | ||||
| var hooks = map[interface{}]HookFunc{} | ||||
|  | ||||
| // Register for notifications on metric registration. The key must be usable as | ||||
| // a key in a map and identifies the hook. No other hook with the same key must | ||||
| // already exist. | ||||
| // | ||||
| // NOTE: The hook will be called for all registrations which already exist. | ||||
| // This ensures that no registrations are missed in a threadsafe manner. | ||||
| // For these calls, the event will be EventRegisterCatchup. | ||||
| // | ||||
| // The hook must not register or unregister registration hooks or metrics. | ||||
| func RegisterHook(key interface{}, hook HookFunc) { | ||||
| 	measurablesMutex.RLock() | ||||
| 	defer measurablesMutex.RUnlock() | ||||
|  | ||||
| 	registerHook(key, hook) | ||||
|  | ||||
| 	for _, m := range measurables { | ||||
| 		hook(m, RegisterCatchupEvent) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func registerHook(key interface{}, hook HookFunc) { | ||||
| 	hooksMutex.Lock() | ||||
| 	defer hooksMutex.Unlock() | ||||
|  | ||||
| 	_, exists := hooks[key] | ||||
| 	if exists { | ||||
| 		panic(fmt.Sprintf("A metric registration hook with the same key already exists: %+v", key)) | ||||
| 	} | ||||
|  | ||||
| 	hooks[key] = hook | ||||
| } | ||||
|  | ||||
| // Unregister an existing hook. | ||||
| func UnregisterHook(key interface{}) { | ||||
| 	hooksMutex.Lock() | ||||
| 	defer hooksMutex.Unlock() | ||||
| 	delete(hooks, key) | ||||
| } | ||||
|  | ||||
| func callRegistrationHooks(measurable Measurable, event HookEvent) { | ||||
| 	hooksMutex.RLock() | ||||
| 	defer hooksMutex.RUnlock() | ||||
|  | ||||
| 	for _, v := range hooks { | ||||
| 		v(measurable, event) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										39
									
								
								vendor/gopkg.in/hlandau/passlib.v1/COPYING
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/gopkg.in/hlandau/passlib.v1/COPYING
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| passlib is a Golang password verification library strongly inspired by and | ||||
| derived from Python passlib (<https://pypi.python.org/pypi/passlib>). The BSD | ||||
| license is preserved and extended to all new code. | ||||
|  | ||||
| License for Passlib | ||||
| =================== | ||||
| Passlib is (c) `Assurance Technologies <http://www.assurancetechnologies.com>`_, | ||||
| and is released under the `BSD license <http://www.opensource.org/licenses/bsd-license.php>`_:: | ||||
|  | ||||
|     Passlib | ||||
|     Copyright (c) 2008-2012 Assurance Technologies, LLC. | ||||
|     All rights reserved. | ||||
|  | ||||
|     Redistribution and use in source and binary forms, with or without | ||||
|     modification, are permitted provided that the following conditions are | ||||
|     met: | ||||
|  | ||||
|     * Redistributions of source code must retain the above copyright | ||||
|       notice, this list of conditions and the following disclaimer. | ||||
|  | ||||
|     * Redistributions in binary form must reproduce the above copyright | ||||
|       notice, this list of conditions and the following disclaimer in the | ||||
|       documentation and/or other materials provided with the distribution. | ||||
|  | ||||
|     * Neither the name of Assurance Technologies, nor the names of the | ||||
|       contributors may be used to endorse or promote products derived | ||||
|       from this software without specific prior written permission. | ||||
|  | ||||
|     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
|     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
|     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
|     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
|     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||
|     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
|     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
							
								
								
									
										11
									
								
								vendor/gopkg.in/hlandau/passlib.v1/abstract/compare.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/gopkg.in/hlandau/passlib.v1/abstract/compare.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| package abstract | ||||
|  | ||||
| import "crypto/subtle" | ||||
|  | ||||
| // Compares two strings (typicaly password hashes) in a secure, constant-time | ||||
| // fashion. Returns true iff they are equal. | ||||
| func SecureCompare(a, b string) bool { | ||||
| 	ab := []byte(a) | ||||
| 	bb := []byte(b) | ||||
| 	return subtle.ConstantTimeCompare(ab, bb) == 1 | ||||
| } | ||||
							
								
								
									
										15
									
								
								vendor/gopkg.in/hlandau/passlib.v1/abstract/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/gopkg.in/hlandau/passlib.v1/abstract/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| // Package abstract contains the abstract description of the Scheme interface, | ||||
| // plus supporting error definitions. | ||||
| package abstract | ||||
|  | ||||
| import "fmt" | ||||
|  | ||||
| // Indicates that password verification failed because the provided password | ||||
| // does not match the provided hash. | ||||
| var ErrInvalidPassword = fmt.Errorf("invalid password") | ||||
|  | ||||
| // Indicates that password verification is not possible because the hashing | ||||
| // scheme used by the hash provided is not supported. | ||||
| var ErrUnsupportedScheme = fmt.Errorf("unsupported scheme") | ||||
|  | ||||
| // © 2014 Hugo Landau <hlandau@devever.net>  MIT License | ||||
							
								
								
									
										34
									
								
								vendor/gopkg.in/hlandau/passlib.v1/abstract/scheme.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/gopkg.in/hlandau/passlib.v1/abstract/scheme.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| package abstract | ||||
|  | ||||
| // The Scheme interface provides an abstract interface to an implementation | ||||
| // of a particular password hashing scheme. The Scheme generates password | ||||
| // hashes from passwords, verifies passwords using password hashes, randomly | ||||
| // generates new stubs and can determines whether it recognises a given | ||||
| // stub or hash. It may also decide to issue upgrades. | ||||
| type Scheme interface { | ||||
| 	// Hashes a plaintext UTF-8 password using a modular crypt stub. Returns the | ||||
| 	// hashed password in modular crypt format. | ||||
| 	// | ||||
| 	// A modular crypt stub is a prefix of a hash in modular crypt format which | ||||
| 	// expresses all necessary configuration information, such as salt and | ||||
| 	// iteration count. For example, for sha256-crypt, a valid stub would be: | ||||
| 	// | ||||
| 	//     $5$rounds=6000$salt | ||||
| 	// | ||||
| 	// A full modular crypt hash may also be passed as the stub, in which case | ||||
| 	// the hash is ignored. | ||||
| 	Hash(password string) (string, error) | ||||
|  | ||||
| 	// Verifies a plaintext UTF-8 password using a modular crypt hash.  Returns | ||||
| 	// an error if the inputs are malformed or the password does not match. | ||||
| 	Verify(password, hash string) (err error) | ||||
|  | ||||
| 	// Returns true iff this crypter supports the given stub. | ||||
| 	SupportsStub(stub string) bool | ||||
|  | ||||
| 	// Returns true iff this stub needs an update. | ||||
| 	NeedsUpdate(stub string) bool | ||||
|  | ||||
| 	// Make a stub with the configured defaults. The salt is generated randomly. | ||||
| 	//MakeStub() (string, error) | ||||
| } | ||||
							
								
								
									
										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