You've already forked nyx
mirror of
https://github.com/rls-moe/nyx
synced 2025-09-13 12:04:13 +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