Compare commits
2 commits
main
...
short_comp
Author | SHA1 | Date | |
---|---|---|---|
29603ae478 | |||
a072d6d6e7 |
676 changed files with 117949 additions and 94718 deletions
28
.github/workflows/go.yml
vendored
28
.github/workflows/go.yml
vendored
|
@ -1,28 +0,0 @@
|
||||||
name: Go
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Set up Go
|
|
||||||
uses: actions/setup-go@v2
|
|
||||||
with:
|
|
||||||
go-version: 1.16
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: make
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: make validation
|
|
||||||
|
|
||||||
- name: Build.Arches
|
|
||||||
run: make build.arches
|
|
|
@ -1,13 +1,21 @@
|
||||||
kind: pipeline
|
language: go
|
||||||
name: default
|
go:
|
||||||
steps:
|
- 1.x
|
||||||
steps:
|
- 1.10.x
|
||||||
- name: build
|
- 1.9.x
|
||||||
image: golang
|
- 1.8.x
|
||||||
commands:
|
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
before_install:
|
||||||
- git config --global url."https://".insteadOf git://
|
- git config --global url."https://".insteadOf git://
|
||||||
- make install.tools
|
- go get -u github.com/golang/lint/golint
|
||||||
|
- go get -u github.com/Masterminds/glide
|
||||||
- mkdir -p $GOPATH/src/github.com/vbatts && ln -sf $(pwd) $GOPATH/src/github.com/vbatts/go-mtree
|
- mkdir -p $GOPATH/src/github.com/vbatts && ln -sf $(pwd) $GOPATH/src/github.com/vbatts/go-mtree
|
||||||
|
|
||||||
|
install: true
|
||||||
|
|
||||||
|
script:
|
||||||
- make validation
|
- make validation
|
||||||
- make validation.tags
|
- make validation.tags
|
||||||
- make build.arches
|
- make build.arches
|
22
Makefile
22
Makefile
|
@ -6,7 +6,6 @@ SOURCE_FILES := $(shell find . -type f -name "*.go")
|
||||||
CLEAN_FILES := *~
|
CLEAN_FILES := *~
|
||||||
TAGS :=
|
TAGS :=
|
||||||
ARCHES := linux,386 linux,amd64 linux,arm linux,arm64 openbsd,amd64 windows,amd64 darwin,amd64
|
ARCHES := linux,386 linux,amd64 linux,arm linux,arm64 openbsd,amd64 windows,amd64 darwin,amd64
|
||||||
GO_VER := go1.14
|
|
||||||
|
|
||||||
default: build validation
|
default: build validation
|
||||||
|
|
||||||
|
@ -20,13 +19,12 @@ validation.tags: .test.tags .vet.tags .cli.test
|
||||||
test: .test
|
test: .test
|
||||||
|
|
||||||
CLEAN_FILES += .test .test.tags
|
CLEAN_FILES += .test .test.tags
|
||||||
NO_VENDOR_DIR := $(shell find . -type f -name '*.go' ! -path './vendor*' ! -path './.git*' ! -path './.vscode*' -exec dirname "{}" \; | sort -u)
|
|
||||||
|
|
||||||
.test: $(SOURCE_FILES)
|
.test: $(SOURCE_FILES)
|
||||||
go test -v $(NO_VENDOR_DIR) && touch $@
|
go test -v $$(glide novendor) && touch $@
|
||||||
|
|
||||||
.test.tags: $(SOURCE_FILES)
|
.test.tags: $(SOURCE_FILES)
|
||||||
set -e ; for tag in $(TAGS) ; do go test -tags $$tag -v $(NO_VENDOR_DIR) ; done && touch $@
|
set -e ; for tag in $(TAGS) ; do go test -tags $$tag -v $$(glide novendor) ; done && touch $@
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: .lint
|
lint: .lint
|
||||||
|
@ -34,11 +32,7 @@ lint: .lint
|
||||||
CLEAN_FILES += .lint
|
CLEAN_FILES += .lint
|
||||||
|
|
||||||
.lint: $(SOURCE_FILES)
|
.lint: $(SOURCE_FILES)
|
||||||
@if [ "$(findstring $(GO_VER),$(shell go version))" != "" ] ; then \
|
set -e ; for dir in $$(glide novendor) ; do golint -set_exit_status $$dir ; done && touch $@
|
||||||
set -e ; for dir in $(NO_VENDOR_DIR) ; do golint -set_exit_status $$dir ; done && touch $@ \
|
|
||||||
else \
|
|
||||||
touch $@ ; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
.PHONY: vet
|
.PHONY: vet
|
||||||
vet: .vet .vet.tags
|
vet: .vet .vet.tags
|
||||||
|
@ -46,10 +40,10 @@ vet: .vet .vet.tags
|
||||||
CLEAN_FILES += .vet .vet.tags
|
CLEAN_FILES += .vet .vet.tags
|
||||||
|
|
||||||
.vet: $(SOURCE_FILES)
|
.vet: $(SOURCE_FILES)
|
||||||
go vet $(NO_VENDOR_DIR) && touch $@
|
go vet $$(glide novendor) && touch $@
|
||||||
|
|
||||||
.vet.tags: $(SOURCE_FILES)
|
.vet.tags: $(SOURCE_FILES)
|
||||||
set -e ; for tag in $(TAGS) ; do go vet -tags $$tag -v $(NO_VENDOR_DIR) ; done && touch $@
|
set -e ; for tag in $(TAGS) ; do go vet -tags $$tag -v $$(glide novendor) ; done && touch $@
|
||||||
|
|
||||||
.PHONY: cli.test
|
.PHONY: cli.test
|
||||||
cli.test: .cli.test
|
cli.test: .cli.test
|
||||||
|
@ -68,12 +62,6 @@ build: $(BUILD)
|
||||||
$(BUILD): $(SOURCE_FILES)
|
$(BUILD): $(SOURCE_FILES)
|
||||||
go build -o $(BUILD) $(BUILDPATH)
|
go build -o $(BUILD) $(BUILDPATH)
|
||||||
|
|
||||||
install.tools:
|
|
||||||
@go get -u github.com/fatih/color ; \
|
|
||||||
if [ "$(findstring $(GO_VER),$(shell go version))" != "" ] ; then \
|
|
||||||
go get -u golang.org/x/lint/golint ;\
|
|
||||||
fi
|
|
||||||
|
|
||||||
./bin:
|
./bin:
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
|
|
16
check.go
16
check.go
|
@ -5,16 +5,26 @@ package mtree
|
||||||
// If keywords is nil, the check all present in the DirectoryHierarchy
|
// If keywords is nil, the check all present in the DirectoryHierarchy
|
||||||
//
|
//
|
||||||
// This is equivalent to creating a new DirectoryHierarchy with Walk(root, nil,
|
// This is equivalent to creating a new DirectoryHierarchy with Walk(root, nil,
|
||||||
// keywords, fs) and then doing a Compare(dh, newDh, keywords).
|
// keywords, fs) and then doing a Compare(dh, curDh, keywords).
|
||||||
func Check(root string, dh *DirectoryHierarchy, keywords []Keyword, fs FsEval) ([]InodeDelta, error) {
|
func Check(root string, dh *DirectoryHierarchy, keywords []Keyword, fs FsEval) ([]InodeDelta, error) {
|
||||||
if keywords == nil {
|
if keywords == nil {
|
||||||
keywords = dh.UsedKeywords()
|
keywords = dh.UsedKeywords()
|
||||||
}
|
}
|
||||||
|
|
||||||
newDh, err := Walk(root, nil, keywords, fs)
|
curDh, err := Walk(root, nil, keywords, fs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return Compare(dh, newDh, keywords)
|
return Compare(dh, curDh, keywords)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TarCheck is the tar equivalent of checking a file hierarchy spec against a
|
||||||
|
// tar stream to determine if files have been changed. This is precisely
|
||||||
|
// equivalent to Compare(dh, tarDH, keywords).
|
||||||
|
func TarCheck(tarDH, dh *DirectoryHierarchy, keywords []Keyword) ([]InodeDelta, error) {
|
||||||
|
if keywords == nil {
|
||||||
|
return Compare(dh, tarDH, dh.UsedKeywords())
|
||||||
|
}
|
||||||
|
return Compare(dh, tarDH, keywords)
|
||||||
}
|
}
|
||||||
|
|
94
compare.go
94
compare.go
|
@ -3,6 +3,7 @@ package mtree
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,10 +31,6 @@ const (
|
||||||
// manifests).
|
// manifests).
|
||||||
Modified DifferenceType = "modified"
|
Modified DifferenceType = "modified"
|
||||||
|
|
||||||
// Same represents the case where two files are the same. These are
|
|
||||||
// only generated from CompareSame().
|
|
||||||
Same DifferenceType = "same"
|
|
||||||
|
|
||||||
// ErrorDifference represents an attempted update to the values of
|
// ErrorDifference represents an attempted update to the values of
|
||||||
// a keyword that failed
|
// a keyword that failed
|
||||||
ErrorDifference DifferenceType = "errored"
|
ErrorDifference DifferenceType = "errored"
|
||||||
|
@ -161,10 +158,10 @@ func (k KeyDelta) Old() *string {
|
||||||
|
|
||||||
// New returns the value of the KeyDeltaVal entry in the "new" DirectoryHierarchy
|
// New returns the value of the KeyDeltaVal entry in the "new" DirectoryHierarchy
|
||||||
// (as determined by the ordering of parameters to Compare). Returns nil if
|
// (as determined by the ordering of parameters to Compare). Returns nil if
|
||||||
// there was no entry in the "new" DirectoryHierarchy.
|
// there was no entry in the "old" DirectoryHierarchy.
|
||||||
func (k KeyDelta) New() *string {
|
func (k KeyDelta) New() *string {
|
||||||
if k.diff == Modified || k.diff == Extra {
|
if k.diff == Modified || k.diff == Extra {
|
||||||
return sPtr(k.new)
|
return sPtr(k.old)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -317,8 +314,29 @@ func compareEntry(oldEntry, newEntry Entry) ([]KeyDelta, error) {
|
||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// compare is the actual workhorse for Compare() and CompareSame()
|
// Compare compares two directory hierarchy manifests, and returns the
|
||||||
func compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword, same bool) ([]InodeDelta, error) {
|
// list of discrepancies between the two. All of the entries in the
|
||||||
|
// manifest are considered, with differences being generated for
|
||||||
|
// RelativeType and FullType entries. Differences in structure (such as
|
||||||
|
// the way /set and /unset are written) are not considered to be
|
||||||
|
// discrepancies. The list of differences are all filesystem objects.
|
||||||
|
//
|
||||||
|
// keys controls which keys will be compared, but if keys is nil then all
|
||||||
|
// possible keys will be compared between the two manifests (allowing for
|
||||||
|
// missing entries and the like). A missing or extra key is treated as a
|
||||||
|
// Modified type.
|
||||||
|
//
|
||||||
|
// If thisDh or thatDh are empty, we assume they are a hierarchy that is
|
||||||
|
// completely empty. This is purely for helping callers create synthetic
|
||||||
|
// InodeDeltas.
|
||||||
|
//
|
||||||
|
// Comparing this directory hierarchy to that directory hierarchy is that
|
||||||
|
// sometimes it has few than all files, or may not have directories, etc.,
|
||||||
|
// so lack of presence of entries in thisDh may not be reportable.
|
||||||
|
//
|
||||||
|
// NB: The order of the parameters matters (old, new) because Extra and
|
||||||
|
// Missing are considered as different discrepancy types.
|
||||||
|
func Compare(thisDh, thatDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, error) {
|
||||||
// Represents the new and old states for an entry.
|
// Represents the new and old states for an entry.
|
||||||
type stateT struct {
|
type stateT struct {
|
||||||
Old *Entry
|
Old *Entry
|
||||||
|
@ -330,8 +348,9 @@ func compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword, same bool) ([]Ino
|
||||||
diffs := map[string]*stateT{}
|
diffs := map[string]*stateT{}
|
||||||
|
|
||||||
// First, iterate over the old hierarchy. If nil, pretend it's empty.
|
// First, iterate over the old hierarchy. If nil, pretend it's empty.
|
||||||
if oldDh != nil {
|
if thisDh != nil {
|
||||||
for _, e := range oldDh.Entries {
|
sort.Sort(byName(thisDh.Entries))
|
||||||
|
for _, e := range thisDh.Entries {
|
||||||
if e.Type == RelativeType || e.Type == FullType {
|
if e.Type == RelativeType || e.Type == FullType {
|
||||||
path, err := e.Path()
|
path, err := e.Path()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -339,21 +358,22 @@ func compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword, same bool) ([]Ino
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cannot take &kv because it's the iterator.
|
// Cannot take &kv because it's the iterator.
|
||||||
cEntry := new(Entry)
|
copy := new(Entry)
|
||||||
*cEntry = e
|
*copy = e
|
||||||
|
|
||||||
_, ok := diffs[path]
|
_, ok := diffs[path]
|
||||||
if !ok {
|
if !ok {
|
||||||
diffs[path] = &stateT{}
|
diffs[path] = &stateT{}
|
||||||
}
|
}
|
||||||
diffs[path].Old = cEntry
|
diffs[path].Old = copy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, iterate over the new hierarchy. If nil, pretend it's empty.
|
// Then, iterate over the new hierarchy. If nil, pretend it's empty.
|
||||||
if newDh != nil {
|
if thatDh != nil {
|
||||||
for _, e := range newDh.Entries {
|
sort.Sort(byName(thatDh.Entries))
|
||||||
|
for _, e := range thatDh.Entries {
|
||||||
if e.Type == RelativeType || e.Type == FullType {
|
if e.Type == RelativeType || e.Type == FullType {
|
||||||
path, err := e.Path()
|
path, err := e.Path()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -361,14 +381,14 @@ func compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword, same bool) ([]Ino
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cannot take &kv because it's the iterator.
|
// Cannot take &kv because it's the iterator.
|
||||||
cEntry := new(Entry)
|
copy := new(Entry)
|
||||||
*cEntry = e
|
*copy = e
|
||||||
|
|
||||||
_, ok := diffs[path]
|
_, ok := diffs[path]
|
||||||
if !ok {
|
if !ok {
|
||||||
diffs[path] = &stateT{}
|
diffs[path] = &stateT{}
|
||||||
}
|
}
|
||||||
diffs[path].New = cEntry
|
diffs[path].New = copy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,47 +445,9 @@ func compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword, same bool) ([]Ino
|
||||||
new: *diff.New,
|
new: *diff.New,
|
||||||
keys: changed,
|
keys: changed,
|
||||||
})
|
})
|
||||||
} else if same {
|
|
||||||
// this means that nothing changed, i.e. that
|
|
||||||
// the files are the same.
|
|
||||||
results = append(results, InodeDelta{
|
|
||||||
diff: Same,
|
|
||||||
path: path,
|
|
||||||
old: *diff.Old,
|
|
||||||
new: *diff.New,
|
|
||||||
keys: changed,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare compares two directory hierarchy manifests, and returns the
|
|
||||||
// list of discrepancies between the two. All of the entries in the
|
|
||||||
// manifest are considered, with differences being generated for
|
|
||||||
// RelativeType and FullType entries. Differences in structure (such as
|
|
||||||
// the way /set and /unset are written) are not considered to be
|
|
||||||
// discrepancies. The list of differences are all filesystem objects.
|
|
||||||
//
|
|
||||||
// keys controls which keys will be compared, but if keys is nil then all
|
|
||||||
// possible keys will be compared between the two manifests (allowing for
|
|
||||||
// missing entries and the like). A missing or extra key is treated as a
|
|
||||||
// Modified type.
|
|
||||||
//
|
|
||||||
// If oldDh or newDh are empty, we assume they are a hierarchy that is
|
|
||||||
// completely empty. This is purely for helping callers create synthetic
|
|
||||||
// InodeDeltas.
|
|
||||||
//
|
|
||||||
// NB: The order of the parameters matters (old, new) because Extra and
|
|
||||||
// Missing are considered as different discrepancy types.
|
|
||||||
func Compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, error) {
|
|
||||||
return compare(oldDh, newDh, keys, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CompareSame is the same as Compare, except it also includes the entries
|
|
||||||
// that are the same with a Same DifferenceType.
|
|
||||||
func CompareSame(oldDh, newDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, error) {
|
|
||||||
return compare(oldDh, newDh, keys, true)
|
|
||||||
}
|
|
||||||
|
|
66
entry.go
66
entry.go
|
@ -2,7 +2,6 @@ package mtree
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -15,6 +14,33 @@ func (bp byPos) Len() int { return len(bp) }
|
||||||
func (bp byPos) Less(i, j int) bool { return bp[i].Pos < bp[j].Pos }
|
func (bp byPos) Less(i, j int) bool { return bp[i].Pos < bp[j].Pos }
|
||||||
func (bp byPos) Swap(i, j int) { bp[i], bp[j] = bp[j], bp[i] }
|
func (bp byPos) Swap(i, j int) { bp[i], bp[j] = bp[j], bp[i] }
|
||||||
|
|
||||||
|
type byName []Entry
|
||||||
|
|
||||||
|
func (bp byName) Len() int { return len(bp) }
|
||||||
|
func (bp byName) Less(i, j int) bool {
|
||||||
|
var iParent string
|
||||||
|
var jParent string
|
||||||
|
var err error
|
||||||
|
if bp[i].Parent != nil {
|
||||||
|
iParent, err = bp[i].Parent.Path()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iName := filepath.Clean(filepath.Join(iParent, bp[i].Name))
|
||||||
|
|
||||||
|
if bp[j].Parent != nil {
|
||||||
|
jParent, err = bp[j].Parent.Path()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jName := filepath.Clean(filepath.Join(jParent, bp[j].Name))
|
||||||
|
|
||||||
|
return iName < jName
|
||||||
|
}
|
||||||
|
func (bp byName) Swap(i, j int) { bp[i], bp[j] = bp[j], bp[i] }
|
||||||
|
|
||||||
// Entry is each component of content in the mtree spec file
|
// Entry is each component of content in the mtree spec file
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
Parent *Entry // up
|
Parent *Entry // up
|
||||||
|
@ -68,39 +94,6 @@ func (e Entry) Ascend() *Entry {
|
||||||
return e.Parent
|
return e.Parent
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanPath makes a path safe for use with filepath.Join. This is done by not
|
|
||||||
// only cleaning the path, but also (if the path is relative) adding a leading
|
|
||||||
// '/' and cleaning it (then removing the leading '/'). This ensures that a
|
|
||||||
// path resulting from prepending another path will always resolve to lexically
|
|
||||||
// be a subdirectory of the prefixed path. This is all done lexically, so paths
|
|
||||||
// that include symlinks won't be safe as a result of using CleanPath.
|
|
||||||
//
|
|
||||||
// This code was copied from runc/libcontainer/utils/utils.go. It was
|
|
||||||
// originally written by myself, so I am dual-licensing it for the purpose of
|
|
||||||
// this project.
|
|
||||||
func CleanPath(path string) string {
|
|
||||||
// Deal with empty strings nicely.
|
|
||||||
if path == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that all paths are cleaned (especially problematic ones like
|
|
||||||
// "/../../../../../" which can cause lots of issues).
|
|
||||||
path = filepath.Clean(path)
|
|
||||||
|
|
||||||
// If the path isn't absolute, we need to do more processing to fix paths
|
|
||||||
// such as "../../../../<etc>/some/path". We also shouldn't convert absolute
|
|
||||||
// paths to relative ones.
|
|
||||||
if !filepath.IsAbs(path) {
|
|
||||||
path = filepath.Clean(string(os.PathSeparator) + path)
|
|
||||||
// This can't fail, as (by definition) all paths are relative to root.
|
|
||||||
path, _ = filepath.Rel(string(os.PathSeparator), path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean the path again for good measure.
|
|
||||||
return filepath.Clean(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Path provides the full path of the file, despite RelativeType or FullType. It
|
// Path provides the full path of the file, despite RelativeType or FullType. It
|
||||||
// will be in Unvis'd form.
|
// will be in Unvis'd form.
|
||||||
func (e Entry) Path() (string, error) {
|
func (e Entry) Path() (string, error) {
|
||||||
|
@ -108,15 +101,14 @@ func (e Entry) Path() (string, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
decodedName = CleanPath(decodedName)
|
|
||||||
if e.Parent == nil || e.Type == FullType {
|
if e.Parent == nil || e.Type == FullType {
|
||||||
return decodedName, nil
|
return filepath.Clean(decodedName), nil
|
||||||
}
|
}
|
||||||
parentName, err := e.Parent.Path()
|
parentName, err := e.Parent.Path()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return CleanPath(filepath.Join(parentName, decodedName)), nil
|
return filepath.Clean(filepath.Join(parentName, decodedName)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// String joins a file with its associated keywords. The file name will be the
|
// String joins a file with its associated keywords. The file name will be the
|
||||||
|
|
15
glide.lock
generated
Normal file
15
glide.lock
generated
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
hash: 72477bc1ec8c50d432740cbf3940cae19387d596c02f1046c7e989458462e536
|
||||||
|
updated: 2017-10-20T11:31:42.730083725+02:00
|
||||||
|
imports:
|
||||||
|
- name: github.com/sirupsen/logrus
|
||||||
|
version: f006c2ac4710855cf0f916dd6b77acf6b048dc6e
|
||||||
|
- name: golang.org/x/crypto
|
||||||
|
version: 1351f936d976c60a0a48d728281922cf63eafb8d
|
||||||
|
subpackages:
|
||||||
|
- ripemd160
|
||||||
|
- ssh/terminal
|
||||||
|
- name: golang.org/x/sys
|
||||||
|
version: 8dbc5d05d6edcc104950cc299a1ce6641235bc86
|
||||||
|
subpackages:
|
||||||
|
- unix
|
||||||
|
testImports: []
|
14
glide.yaml
Normal file
14
glide.yaml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package: github.com/vbatts/go-mtree
|
||||||
|
description: File systems verification utility and library, in likeness of mtree(8)
|
||||||
|
homepage: https://github.com/vbatts/go-mtree
|
||||||
|
license: BSD-3-Clause
|
||||||
|
import:
|
||||||
|
- package: golang.org/x/crypto
|
||||||
|
subpackages:
|
||||||
|
- ripemd160
|
||||||
|
- package: github.com/sirupsen/logrus
|
||||||
|
version: ^1.0.0
|
||||||
|
- package: golang.org/x/sys
|
||||||
|
version: 8dbc5d05d6edcc104950cc299a1ce6641235bc86
|
||||||
|
subpackages:
|
||||||
|
- unix
|
11
go.mod
11
go.mod
|
@ -1,11 +0,0 @@
|
||||||
module github.com/vbatts/go-mtree
|
|
||||||
|
|
||||||
go 1.13
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/davecgh/go-spew v1.1.1
|
|
||||||
github.com/fatih/color v1.12.0 // indirect
|
|
||||||
github.com/sirupsen/logrus v1.7.0
|
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
|
||||||
)
|
|
26
go.sum
26
go.sum
|
@ -1,26 +0,0 @@
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
|
|
||||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
|
||||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
|
||||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
|
||||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
|
||||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
|
@ -4,8 +4,6 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -56,15 +54,14 @@ func TestParser(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if i == 1 {
|
if i == 1 {
|
||||||
spew.Dump(dh)
|
buf, err := xml.MarshalIndent(dh, "", " ")
|
||||||
//buf, err := xml.MarshalIndent(dh, "", " ")
|
if err == nil {
|
||||||
//if err == nil {
|
t.Error(string(buf))
|
||||||
//t.Error(string(buf))
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
gotNums := countTypes(dh)
|
gotNums := countTypes(dh)
|
||||||
for typ, num := range tf.Counts {
|
for typ, num := range tf.Counts {
|
||||||
if gNum, ok := gotNums[typ]; ok {
|
if gNum, ok := gotNums[typ]; ok {
|
||||||
|
|
|
@ -109,7 +109,7 @@ func TestTar(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := Compare(tdh, dh, append(DefaultKeywords, "sha1"))
|
res, err := TarCheck(tdh, dh, append(DefaultKeywords, "sha1"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ func TestArchiveCreation(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the tar manifest against itself
|
// Test the tar manifest against itself
|
||||||
res, err = Compare(tdh, tdh, []Keyword{"sha1"})
|
res, err = TarCheck(tdh, tdh, []Keyword{"sha1"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ func TestArchiveCreation(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
res, err = Compare(tdh, dh, []Keyword{"sha1"})
|
res, err = TarCheck(tdh, dh, []Keyword{"sha1"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,7 @@ func TestTreeTraversal(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := Compare(tdh, tdh, []Keyword{"sha1"})
|
res, err := TarCheck(tdh, tdh, []Keyword{"sha1"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
10
test/cli.go
10
test/cli.go
|
@ -7,14 +7,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
green := color.New(color.FgGreen).SprintFunc()
|
|
||||||
red := color.New(color.FgRed).SprintFunc()
|
|
||||||
|
|
||||||
failed := 0
|
failed := 0
|
||||||
for _, arg := range flag.Args() {
|
for _, arg := range flag.Args() {
|
||||||
|
@ -26,12 +22,12 @@ func main() {
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
failed++
|
failed++
|
||||||
fmt.Fprintf(os.Stderr, red("FAILED: %s\n"), arg)
|
fmt.Fprintf(os.Stderr, "FAILED: %s\n", arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if failed > 0 {
|
if failed > 0 {
|
||||||
fmt.Fprintf(os.Stderr, red("%d FAILED tests\n"), failed)
|
fmt.Fprintf(os.Stderr, "%d FAILED tests\n", failed)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stdout, green("SUCCESS: no cli tests failed\n"))
|
fmt.Fprintf(os.Stdout, "SUCCESS: no cli tests failed\n")
|
||||||
}
|
}
|
||||||
|
|
15
vendor/github.com/davecgh/go-spew/LICENSE
generated
vendored
15
vendor/github.com/davecgh/go-spew/LICENSE
generated
vendored
|
@ -1,15 +0,0 @@
|
||||||
ISC License
|
|
||||||
|
|
||||||
Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
145
vendor/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
145
vendor/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
|
@ -1,145 +0,0 @@
|
||||||
// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
|
|
||||||
//
|
|
||||||
// Permission to use, copy, modify, and distribute this software for any
|
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
|
||||||
// copyright notice and this permission notice appear in all copies.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
// NOTE: Due to the following build constraints, this file will only be compiled
|
|
||||||
// when the code is not running on Google App Engine, compiled by GopherJS, and
|
|
||||||
// "-tags safe" is not added to the go build command line. The "disableunsafe"
|
|
||||||
// tag is deprecated and thus should not be used.
|
|
||||||
// Go versions prior to 1.4 are disabled because they use a different layout
|
|
||||||
// for interfaces which make the implementation of unsafeReflectValue more complex.
|
|
||||||
// +build !js,!appengine,!safe,!disableunsafe,go1.4
|
|
||||||
|
|
||||||
package spew
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// UnsafeDisabled is a build-time constant which specifies whether or
|
|
||||||
// not access to the unsafe package is available.
|
|
||||||
UnsafeDisabled = false
|
|
||||||
|
|
||||||
// ptrSize is the size of a pointer on the current arch.
|
|
||||||
ptrSize = unsafe.Sizeof((*byte)(nil))
|
|
||||||
)
|
|
||||||
|
|
||||||
type flag uintptr
|
|
||||||
|
|
||||||
var (
|
|
||||||
// flagRO indicates whether the value field of a reflect.Value
|
|
||||||
// is read-only.
|
|
||||||
flagRO flag
|
|
||||||
|
|
||||||
// flagAddr indicates whether the address of the reflect.Value's
|
|
||||||
// value may be taken.
|
|
||||||
flagAddr flag
|
|
||||||
)
|
|
||||||
|
|
||||||
// flagKindMask holds the bits that make up the kind
|
|
||||||
// part of the flags field. In all the supported versions,
|
|
||||||
// it is in the lower 5 bits.
|
|
||||||
const flagKindMask = flag(0x1f)
|
|
||||||
|
|
||||||
// Different versions of Go have used different
|
|
||||||
// bit layouts for the flags type. This table
|
|
||||||
// records the known combinations.
|
|
||||||
var okFlags = []struct {
|
|
||||||
ro, addr flag
|
|
||||||
}{{
|
|
||||||
// From Go 1.4 to 1.5
|
|
||||||
ro: 1 << 5,
|
|
||||||
addr: 1 << 7,
|
|
||||||
}, {
|
|
||||||
// Up to Go tip.
|
|
||||||
ro: 1<<5 | 1<<6,
|
|
||||||
addr: 1 << 8,
|
|
||||||
}}
|
|
||||||
|
|
||||||
var flagValOffset = func() uintptr {
|
|
||||||
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
|
|
||||||
if !ok {
|
|
||||||
panic("reflect.Value has no flag field")
|
|
||||||
}
|
|
||||||
return field.Offset
|
|
||||||
}()
|
|
||||||
|
|
||||||
// flagField returns a pointer to the flag field of a reflect.Value.
|
|
||||||
func flagField(v *reflect.Value) *flag {
|
|
||||||
return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset))
|
|
||||||
}
|
|
||||||
|
|
||||||
// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
|
|
||||||
// the typical safety restrictions preventing access to unaddressable and
|
|
||||||
// unexported data. It works by digging the raw pointer to the underlying
|
|
||||||
// value out of the protected value and generating a new unprotected (unsafe)
|
|
||||||
// reflect.Value to it.
|
|
||||||
//
|
|
||||||
// This allows us to check for implementations of the Stringer and error
|
|
||||||
// interfaces to be used for pretty printing ordinarily unaddressable and
|
|
||||||
// inaccessible values such as unexported struct fields.
|
|
||||||
func unsafeReflectValue(v reflect.Value) reflect.Value {
|
|
||||||
if !v.IsValid() || (v.CanInterface() && v.CanAddr()) {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
flagFieldPtr := flagField(&v)
|
|
||||||
*flagFieldPtr &^= flagRO
|
|
||||||
*flagFieldPtr |= flagAddr
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanity checks against future reflect package changes
|
|
||||||
// to the type or semantics of the Value.flag field.
|
|
||||||
func init() {
|
|
||||||
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
|
|
||||||
if !ok {
|
|
||||||
panic("reflect.Value has no flag field")
|
|
||||||
}
|
|
||||||
if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() {
|
|
||||||
panic("reflect.Value flag field has changed kind")
|
|
||||||
}
|
|
||||||
type t0 int
|
|
||||||
var t struct {
|
|
||||||
A t0
|
|
||||||
// t0 will have flagEmbedRO set.
|
|
||||||
t0
|
|
||||||
// a will have flagStickyRO set
|
|
||||||
a t0
|
|
||||||
}
|
|
||||||
vA := reflect.ValueOf(t).FieldByName("A")
|
|
||||||
va := reflect.ValueOf(t).FieldByName("a")
|
|
||||||
vt0 := reflect.ValueOf(t).FieldByName("t0")
|
|
||||||
|
|
||||||
// Infer flagRO from the difference between the flags
|
|
||||||
// for the (otherwise identical) fields in t.
|
|
||||||
flagPublic := *flagField(&vA)
|
|
||||||
flagWithRO := *flagField(&va) | *flagField(&vt0)
|
|
||||||
flagRO = flagPublic ^ flagWithRO
|
|
||||||
|
|
||||||
// Infer flagAddr from the difference between a value
|
|
||||||
// taken from a pointer and not.
|
|
||||||
vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A")
|
|
||||||
flagNoPtr := *flagField(&vA)
|
|
||||||
flagPtr := *flagField(&vPtrA)
|
|
||||||
flagAddr = flagNoPtr ^ flagPtr
|
|
||||||
|
|
||||||
// Check that the inferred flags tally with one of the known versions.
|
|
||||||
for _, f := range okFlags {
|
|
||||||
if flagRO == f.ro && flagAddr == f.addr {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic("reflect.Value read-only flag has changed semantics")
|
|
||||||
}
|
|
38
vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
generated
vendored
38
vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
generated
vendored
|
@ -1,38 +0,0 @@
|
||||||
// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
|
|
||||||
//
|
|
||||||
// Permission to use, copy, modify, and distribute this software for any
|
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
|
||||||
// copyright notice and this permission notice appear in all copies.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
// NOTE: Due to the following build constraints, this file will only be compiled
|
|
||||||
// when the code is running on Google App Engine, compiled by GopherJS, or
|
|
||||||
// "-tags safe" is added to the go build command line. The "disableunsafe"
|
|
||||||
// tag is deprecated and thus should not be used.
|
|
||||||
// +build js appengine safe disableunsafe !go1.4
|
|
||||||
|
|
||||||
package spew
|
|
||||||
|
|
||||||
import "reflect"
|
|
||||||
|
|
||||||
const (
|
|
||||||
// UnsafeDisabled is a build-time constant which specifies whether or
|
|
||||||
// not access to the unsafe package is available.
|
|
||||||
UnsafeDisabled = true
|
|
||||||
)
|
|
||||||
|
|
||||||
// unsafeReflectValue typically converts the passed reflect.Value into a one
|
|
||||||
// that bypasses the typical safety restrictions preventing access to
|
|
||||||
// unaddressable and unexported data. However, doing this relies on access to
|
|
||||||
// the unsafe package. This is a stub version which simply returns the passed
|
|
||||||
// reflect.Value when the unsafe package is not available.
|
|
||||||
func unsafeReflectValue(v reflect.Value) reflect.Value {
|
|
||||||
return v
|
|
||||||
}
|
|
341
vendor/github.com/davecgh/go-spew/spew/common.go
generated
vendored
341
vendor/github.com/davecgh/go-spew/spew/common.go
generated
vendored
|
@ -1,341 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package spew
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Some constants in the form of bytes to avoid string overhead. This mirrors
|
|
||||||
// the technique used in the fmt package.
|
|
||||||
var (
|
|
||||||
panicBytes = []byte("(PANIC=")
|
|
||||||
plusBytes = []byte("+")
|
|
||||||
iBytes = []byte("i")
|
|
||||||
trueBytes = []byte("true")
|
|
||||||
falseBytes = []byte("false")
|
|
||||||
interfaceBytes = []byte("(interface {})")
|
|
||||||
commaNewlineBytes = []byte(",\n")
|
|
||||||
newlineBytes = []byte("\n")
|
|
||||||
openBraceBytes = []byte("{")
|
|
||||||
openBraceNewlineBytes = []byte("{\n")
|
|
||||||
closeBraceBytes = []byte("}")
|
|
||||||
asteriskBytes = []byte("*")
|
|
||||||
colonBytes = []byte(":")
|
|
||||||
colonSpaceBytes = []byte(": ")
|
|
||||||
openParenBytes = []byte("(")
|
|
||||||
closeParenBytes = []byte(")")
|
|
||||||
spaceBytes = []byte(" ")
|
|
||||||
pointerChainBytes = []byte("->")
|
|
||||||
nilAngleBytes = []byte("<nil>")
|
|
||||||
maxNewlineBytes = []byte("<max depth reached>\n")
|
|
||||||
maxShortBytes = []byte("<max>")
|
|
||||||
circularBytes = []byte("<already shown>")
|
|
||||||
circularShortBytes = []byte("<shown>")
|
|
||||||
invalidAngleBytes = []byte("<invalid>")
|
|
||||||
openBracketBytes = []byte("[")
|
|
||||||
closeBracketBytes = []byte("]")
|
|
||||||
percentBytes = []byte("%")
|
|
||||||
precisionBytes = []byte(".")
|
|
||||||
openAngleBytes = []byte("<")
|
|
||||||
closeAngleBytes = []byte(">")
|
|
||||||
openMapBytes = []byte("map[")
|
|
||||||
closeMapBytes = []byte("]")
|
|
||||||
lenEqualsBytes = []byte("len=")
|
|
||||||
capEqualsBytes = []byte("cap=")
|
|
||||||
)
|
|
||||||
|
|
||||||
// hexDigits is used to map a decimal value to a hex digit.
|
|
||||||
var hexDigits = "0123456789abcdef"
|
|
||||||
|
|
||||||
// catchPanic handles any panics that might occur during the handleMethods
|
|
||||||
// calls.
|
|
||||||
func catchPanic(w io.Writer, v reflect.Value) {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
w.Write(panicBytes)
|
|
||||||
fmt.Fprintf(w, "%v", err)
|
|
||||||
w.Write(closeParenBytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleMethods attempts to call the Error and String methods on the underlying
|
|
||||||
// type the passed reflect.Value represents and outputes the result to Writer w.
|
|
||||||
//
|
|
||||||
// It handles panics in any called methods by catching and displaying the error
|
|
||||||
// as the formatted value.
|
|
||||||
func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
|
|
||||||
// We need an interface to check if the type implements the error or
|
|
||||||
// Stringer interface. However, the reflect package won't give us an
|
|
||||||
// interface on certain things like unexported struct fields in order
|
|
||||||
// to enforce visibility rules. We use unsafe, when it's available,
|
|
||||||
// to bypass these restrictions since this package does not mutate the
|
|
||||||
// values.
|
|
||||||
if !v.CanInterface() {
|
|
||||||
if UnsafeDisabled {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
v = unsafeReflectValue(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Choose whether or not to do error and Stringer interface lookups against
|
|
||||||
// the base type or a pointer to the base type depending on settings.
|
|
||||||
// Technically calling one of these methods with a pointer receiver can
|
|
||||||
// mutate the value, however, types which choose to satisify an error or
|
|
||||||
// Stringer interface with a pointer receiver should not be mutating their
|
|
||||||
// state inside these interface methods.
|
|
||||||
if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() {
|
|
||||||
v = unsafeReflectValue(v)
|
|
||||||
}
|
|
||||||
if v.CanAddr() {
|
|
||||||
v = v.Addr()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is it an error or Stringer?
|
|
||||||
switch iface := v.Interface().(type) {
|
|
||||||
case error:
|
|
||||||
defer catchPanic(w, v)
|
|
||||||
if cs.ContinueOnMethod {
|
|
||||||
w.Write(openParenBytes)
|
|
||||||
w.Write([]byte(iface.Error()))
|
|
||||||
w.Write(closeParenBytes)
|
|
||||||
w.Write(spaceBytes)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Write([]byte(iface.Error()))
|
|
||||||
return true
|
|
||||||
|
|
||||||
case fmt.Stringer:
|
|
||||||
defer catchPanic(w, v)
|
|
||||||
if cs.ContinueOnMethod {
|
|
||||||
w.Write(openParenBytes)
|
|
||||||
w.Write([]byte(iface.String()))
|
|
||||||
w.Write(closeParenBytes)
|
|
||||||
w.Write(spaceBytes)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
w.Write([]byte(iface.String()))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// printBool outputs a boolean value as true or false to Writer w.
|
|
||||||
func printBool(w io.Writer, val bool) {
|
|
||||||
if val {
|
|
||||||
w.Write(trueBytes)
|
|
||||||
} else {
|
|
||||||
w.Write(falseBytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// printInt outputs a signed integer value to Writer w.
|
|
||||||
func printInt(w io.Writer, val int64, base int) {
|
|
||||||
w.Write([]byte(strconv.FormatInt(val, base)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// printUint outputs an unsigned integer value to Writer w.
|
|
||||||
func printUint(w io.Writer, val uint64, base int) {
|
|
||||||
w.Write([]byte(strconv.FormatUint(val, base)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// printFloat outputs a floating point value using the specified precision,
|
|
||||||
// which is expected to be 32 or 64bit, to Writer w.
|
|
||||||
func printFloat(w io.Writer, val float64, precision int) {
|
|
||||||
w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// printComplex outputs a complex value using the specified float precision
|
|
||||||
// for the real and imaginary parts to Writer w.
|
|
||||||
func printComplex(w io.Writer, c complex128, floatPrecision int) {
|
|
||||||
r := real(c)
|
|
||||||
w.Write(openParenBytes)
|
|
||||||
w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
|
|
||||||
i := imag(c)
|
|
||||||
if i >= 0 {
|
|
||||||
w.Write(plusBytes)
|
|
||||||
}
|
|
||||||
w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
|
|
||||||
w.Write(iBytes)
|
|
||||||
w.Write(closeParenBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
|
|
||||||
// prefix to Writer w.
|
|
||||||
func printHexPtr(w io.Writer, p uintptr) {
|
|
||||||
// Null pointer.
|
|
||||||
num := uint64(p)
|
|
||||||
if num == 0 {
|
|
||||||
w.Write(nilAngleBytes)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
|
|
||||||
buf := make([]byte, 18)
|
|
||||||
|
|
||||||
// It's simpler to construct the hex string right to left.
|
|
||||||
base := uint64(16)
|
|
||||||
i := len(buf) - 1
|
|
||||||
for num >= base {
|
|
||||||
buf[i] = hexDigits[num%base]
|
|
||||||
num /= base
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
buf[i] = hexDigits[num]
|
|
||||||
|
|
||||||
// Add '0x' prefix.
|
|
||||||
i--
|
|
||||||
buf[i] = 'x'
|
|
||||||
i--
|
|
||||||
buf[i] = '0'
|
|
||||||
|
|
||||||
// Strip unused leading bytes.
|
|
||||||
buf = buf[i:]
|
|
||||||
w.Write(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// valuesSorter implements sort.Interface to allow a slice of reflect.Value
|
|
||||||
// elements to be sorted.
|
|
||||||
type valuesSorter struct {
|
|
||||||
values []reflect.Value
|
|
||||||
strings []string // either nil or same len and values
|
|
||||||
cs *ConfigState
|
|
||||||
}
|
|
||||||
|
|
||||||
// newValuesSorter initializes a valuesSorter instance, which holds a set of
|
|
||||||
// surrogate keys on which the data should be sorted. It uses flags in
|
|
||||||
// ConfigState to decide if and how to populate those surrogate keys.
|
|
||||||
func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface {
|
|
||||||
vs := &valuesSorter{values: values, cs: cs}
|
|
||||||
if canSortSimply(vs.values[0].Kind()) {
|
|
||||||
return vs
|
|
||||||
}
|
|
||||||
if !cs.DisableMethods {
|
|
||||||
vs.strings = make([]string, len(values))
|
|
||||||
for i := range vs.values {
|
|
||||||
b := bytes.Buffer{}
|
|
||||||
if !handleMethods(cs, &b, vs.values[i]) {
|
|
||||||
vs.strings = nil
|
|
||||||
break
|
|
||||||
}
|
|
||||||
vs.strings[i] = b.String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if vs.strings == nil && cs.SpewKeys {
|
|
||||||
vs.strings = make([]string, len(values))
|
|
||||||
for i := range vs.values {
|
|
||||||
vs.strings[i] = Sprintf("%#v", vs.values[i].Interface())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return vs
|
|
||||||
}
|
|
||||||
|
|
||||||
// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
|
|
||||||
// directly, or whether it should be considered for sorting by surrogate keys
|
|
||||||
// (if the ConfigState allows it).
|
|
||||||
func canSortSimply(kind reflect.Kind) bool {
|
|
||||||
// This switch parallels valueSortLess, except for the default case.
|
|
||||||
switch kind {
|
|
||||||
case reflect.Bool:
|
|
||||||
return true
|
|
||||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
|
||||||
return true
|
|
||||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
|
||||||
return true
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
return true
|
|
||||||
case reflect.String:
|
|
||||||
return true
|
|
||||||
case reflect.Uintptr:
|
|
||||||
return true
|
|
||||||
case reflect.Array:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len returns the number of values in the slice. It is part of the
|
|
||||||
// sort.Interface implementation.
|
|
||||||
func (s *valuesSorter) Len() int {
|
|
||||||
return len(s.values)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap swaps the values at the passed indices. It is part of the
|
|
||||||
// sort.Interface implementation.
|
|
||||||
func (s *valuesSorter) Swap(i, j int) {
|
|
||||||
s.values[i], s.values[j] = s.values[j], s.values[i]
|
|
||||||
if s.strings != nil {
|
|
||||||
s.strings[i], s.strings[j] = s.strings[j], s.strings[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// valueSortLess returns whether the first value should sort before the second
|
|
||||||
// value. It is used by valueSorter.Less as part of the sort.Interface
|
|
||||||
// implementation.
|
|
||||||
func valueSortLess(a, b reflect.Value) bool {
|
|
||||||
switch a.Kind() {
|
|
||||||
case reflect.Bool:
|
|
||||||
return !a.Bool() && b.Bool()
|
|
||||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
|
||||||
return a.Int() < b.Int()
|
|
||||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
|
||||||
return a.Uint() < b.Uint()
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
return a.Float() < b.Float()
|
|
||||||
case reflect.String:
|
|
||||||
return a.String() < b.String()
|
|
||||||
case reflect.Uintptr:
|
|
||||||
return a.Uint() < b.Uint()
|
|
||||||
case reflect.Array:
|
|
||||||
// Compare the contents of both arrays.
|
|
||||||
l := a.Len()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
av := a.Index(i)
|
|
||||||
bv := b.Index(i)
|
|
||||||
if av.Interface() == bv.Interface() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return valueSortLess(av, bv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return a.String() < b.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Less returns whether the value at index i should sort before the
|
|
||||||
// value at index j. It is part of the sort.Interface implementation.
|
|
||||||
func (s *valuesSorter) Less(i, j int) bool {
|
|
||||||
if s.strings == nil {
|
|
||||||
return valueSortLess(s.values[i], s.values[j])
|
|
||||||
}
|
|
||||||
return s.strings[i] < s.strings[j]
|
|
||||||
}
|
|
||||||
|
|
||||||
// sortValues is a sort function that handles both native types and any type that
|
|
||||||
// can be converted to error or Stringer. Other inputs are sorted according to
|
|
||||||
// their Value.String() value to ensure display stability.
|
|
||||||
func sortValues(values []reflect.Value, cs *ConfigState) {
|
|
||||||
if len(values) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sort.Sort(newValuesSorter(values, cs))
|
|
||||||
}
|
|
306
vendor/github.com/davecgh/go-spew/spew/config.go
generated
vendored
306
vendor/github.com/davecgh/go-spew/spew/config.go
generated
vendored
|
@ -1,306 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package spew
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ConfigState houses the configuration options used by spew to format and
|
|
||||||
// display values. There is a global instance, Config, that is used to control
|
|
||||||
// all top-level Formatter and Dump functionality. Each ConfigState instance
|
|
||||||
// provides methods equivalent to the top-level functions.
|
|
||||||
//
|
|
||||||
// The zero value for ConfigState provides no indentation. You would typically
|
|
||||||
// want to set it to a space or a tab.
|
|
||||||
//
|
|
||||||
// Alternatively, you can use NewDefaultConfig to get a ConfigState instance
|
|
||||||
// with default settings. See the documentation of NewDefaultConfig for default
|
|
||||||
// values.
|
|
||||||
type ConfigState struct {
|
|
||||||
// Indent specifies the string to use for each indentation level. The
|
|
||||||
// global config instance that all top-level functions use set this to a
|
|
||||||
// single space by default. If you would like more indentation, you might
|
|
||||||
// set this to a tab with "\t" or perhaps two spaces with " ".
|
|
||||||
Indent string
|
|
||||||
|
|
||||||
// MaxDepth controls the maximum number of levels to descend into nested
|
|
||||||
// data structures. The default, 0, means there is no limit.
|
|
||||||
//
|
|
||||||
// NOTE: Circular data structures are properly detected, so it is not
|
|
||||||
// necessary to set this value unless you specifically want to limit deeply
|
|
||||||
// nested data structures.
|
|
||||||
MaxDepth int
|
|
||||||
|
|
||||||
// DisableMethods specifies whether or not error and Stringer interfaces are
|
|
||||||
// invoked for types that implement them.
|
|
||||||
DisableMethods bool
|
|
||||||
|
|
||||||
// DisablePointerMethods specifies whether or not to check for and invoke
|
|
||||||
// error and Stringer interfaces on types which only accept a pointer
|
|
||||||
// receiver when the current type is not a pointer.
|
|
||||||
//
|
|
||||||
// NOTE: This might be an unsafe action since calling one of these methods
|
|
||||||
// with a pointer receiver could technically mutate the value, however,
|
|
||||||
// in practice, types which choose to satisify an error or Stringer
|
|
||||||
// interface with a pointer receiver should not be mutating their state
|
|
||||||
// inside these interface methods. As a result, this option relies on
|
|
||||||
// access to the unsafe package, so it will not have any effect when
|
|
||||||
// running in environments without access to the unsafe package such as
|
|
||||||
// Google App Engine or with the "safe" build tag specified.
|
|
||||||
DisablePointerMethods bool
|
|
||||||
|
|
||||||
// DisablePointerAddresses specifies whether to disable the printing of
|
|
||||||
// pointer addresses. This is useful when diffing data structures in tests.
|
|
||||||
DisablePointerAddresses bool
|
|
||||||
|
|
||||||
// DisableCapacities specifies whether to disable the printing of capacities
|
|
||||||
// for arrays, slices, maps and channels. This is useful when diffing
|
|
||||||
// data structures in tests.
|
|
||||||
DisableCapacities bool
|
|
||||||
|
|
||||||
// ContinueOnMethod specifies whether or not recursion should continue once
|
|
||||||
// a custom error or Stringer interface is invoked. The default, false,
|
|
||||||
// means it will print the results of invoking the custom error or Stringer
|
|
||||||
// interface and return immediately instead of continuing to recurse into
|
|
||||||
// the internals of the data type.
|
|
||||||
//
|
|
||||||
// NOTE: This flag does not have any effect if method invocation is disabled
|
|
||||||
// via the DisableMethods or DisablePointerMethods options.
|
|
||||||
ContinueOnMethod bool
|
|
||||||
|
|
||||||
// SortKeys specifies map keys should be sorted before being printed. Use
|
|
||||||
// this to have a more deterministic, diffable output. Note that only
|
|
||||||
// native types (bool, int, uint, floats, uintptr and string) and types
|
|
||||||
// that support the error or Stringer interfaces (if methods are
|
|
||||||
// enabled) are supported, with other types sorted according to the
|
|
||||||
// reflect.Value.String() output which guarantees display stability.
|
|
||||||
SortKeys bool
|
|
||||||
|
|
||||||
// SpewKeys specifies that, as a last resort attempt, map keys should
|
|
||||||
// be spewed to strings and sorted by those strings. This is only
|
|
||||||
// considered if SortKeys is true.
|
|
||||||
SpewKeys bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config is the active configuration of the top-level functions.
|
|
||||||
// The configuration can be changed by modifying the contents of spew.Config.
|
|
||||||
var Config = ConfigState{Indent: " "}
|
|
||||||
|
|
||||||
// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
|
|
||||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
|
||||||
// the formatted string as a value that satisfies error. See NewFormatter
|
|
||||||
// for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b))
|
|
||||||
func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) {
|
|
||||||
return fmt.Errorf(format, c.convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
|
|
||||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
|
||||||
// the number of bytes written and any write error encountered. See
|
|
||||||
// NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b))
|
|
||||||
func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
|
|
||||||
return fmt.Fprint(w, c.convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
|
|
||||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
|
||||||
// the number of bytes written and any write error encountered. See
|
|
||||||
// NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b))
|
|
||||||
func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
|
|
||||||
return fmt.Fprintf(w, format, c.convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
|
|
||||||
// passed with a Formatter interface returned by c.NewFormatter. See
|
|
||||||
// NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b))
|
|
||||||
func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
|
|
||||||
return fmt.Fprintln(w, c.convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print is a wrapper for fmt.Print that treats each argument as if it were
|
|
||||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
|
||||||
// the number of bytes written and any write error encountered. See
|
|
||||||
// NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Print(c.NewFormatter(a), c.NewFormatter(b))
|
|
||||||
func (c *ConfigState) Print(a ...interface{}) (n int, err error) {
|
|
||||||
return fmt.Print(c.convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Printf is a wrapper for fmt.Printf that treats each argument as if it were
|
|
||||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
|
||||||
// the number of bytes written and any write error encountered. See
|
|
||||||
// NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b))
|
|
||||||
func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) {
|
|
||||||
return fmt.Printf(format, c.convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Println is a wrapper for fmt.Println that treats each argument as if it were
|
|
||||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
|
||||||
// the number of bytes written and any write error encountered. See
|
|
||||||
// NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Println(c.NewFormatter(a), c.NewFormatter(b))
|
|
||||||
func (c *ConfigState) Println(a ...interface{}) (n int, err error) {
|
|
||||||
return fmt.Println(c.convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
|
|
||||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
|
||||||
// the resulting string. See NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b))
|
|
||||||
func (c *ConfigState) Sprint(a ...interface{}) string {
|
|
||||||
return fmt.Sprint(c.convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
|
|
||||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
|
||||||
// the resulting string. See NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b))
|
|
||||||
func (c *ConfigState) Sprintf(format string, a ...interface{}) string {
|
|
||||||
return fmt.Sprintf(format, c.convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
|
|
||||||
// were passed with a Formatter interface returned by c.NewFormatter. It
|
|
||||||
// returns the resulting string. See NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b))
|
|
||||||
func (c *ConfigState) Sprintln(a ...interface{}) string {
|
|
||||||
return fmt.Sprintln(c.convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
NewFormatter returns a custom formatter that satisfies the fmt.Formatter
|
|
||||||
interface. As a result, it integrates cleanly with standard fmt package
|
|
||||||
printing functions. The formatter is useful for inline printing of smaller data
|
|
||||||
types similar to the standard %v format specifier.
|
|
||||||
|
|
||||||
The custom formatter only responds to the %v (most compact), %+v (adds pointer
|
|
||||||
addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb
|
|
||||||
combinations. Any other verbs such as %x and %q will be sent to the the
|
|
||||||
standard fmt package for formatting. In addition, the custom formatter ignores
|
|
||||||
the width and precision arguments (however they will still work on the format
|
|
||||||
specifiers not handled by the custom formatter).
|
|
||||||
|
|
||||||
Typically this function shouldn't be called directly. It is much easier to make
|
|
||||||
use of the custom formatter by calling one of the convenience functions such as
|
|
||||||
c.Printf, c.Println, or c.Printf.
|
|
||||||
*/
|
|
||||||
func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter {
|
|
||||||
return newFormatter(c, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fdump formats and displays the passed arguments to io.Writer w. It formats
|
|
||||||
// exactly the same as Dump.
|
|
||||||
func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) {
|
|
||||||
fdump(c, w, a...)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Dump displays the passed parameters to standard out with newlines, customizable
|
|
||||||
indentation, and additional debug information such as complete types and all
|
|
||||||
pointer addresses used to indirect to the final value. It provides the
|
|
||||||
following features over the built-in printing facilities provided by the fmt
|
|
||||||
package:
|
|
||||||
|
|
||||||
* Pointers are dereferenced and followed
|
|
||||||
* Circular data structures are detected and handled properly
|
|
||||||
* Custom Stringer/error interfaces are optionally invoked, including
|
|
||||||
on unexported types
|
|
||||||
* Custom types which only implement the Stringer/error interfaces via
|
|
||||||
a pointer receiver are optionally invoked when passing non-pointer
|
|
||||||
variables
|
|
||||||
* Byte arrays and slices are dumped like the hexdump -C command which
|
|
||||||
includes offsets, byte values in hex, and ASCII output
|
|
||||||
|
|
||||||
The configuration options are controlled by modifying the public members
|
|
||||||
of c. See ConfigState for options documentation.
|
|
||||||
|
|
||||||
See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
|
|
||||||
get the formatted result as a string.
|
|
||||||
*/
|
|
||||||
func (c *ConfigState) Dump(a ...interface{}) {
|
|
||||||
fdump(c, os.Stdout, a...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sdump returns a string with the passed arguments formatted exactly the same
|
|
||||||
// as Dump.
|
|
||||||
func (c *ConfigState) Sdump(a ...interface{}) string {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
fdump(c, &buf, a...)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertArgs accepts a slice of arguments and returns a slice of the same
|
|
||||||
// length with each argument converted to a spew Formatter interface using
|
|
||||||
// the ConfigState associated with s.
|
|
||||||
func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) {
|
|
||||||
formatters = make([]interface{}, len(args))
|
|
||||||
for index, arg := range args {
|
|
||||||
formatters[index] = newFormatter(c, arg)
|
|
||||||
}
|
|
||||||
return formatters
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDefaultConfig returns a ConfigState with the following default settings.
|
|
||||||
//
|
|
||||||
// Indent: " "
|
|
||||||
// MaxDepth: 0
|
|
||||||
// DisableMethods: false
|
|
||||||
// DisablePointerMethods: false
|
|
||||||
// ContinueOnMethod: false
|
|
||||||
// SortKeys: false
|
|
||||||
func NewDefaultConfig() *ConfigState {
|
|
||||||
return &ConfigState{Indent: " "}
|
|
||||||
}
|
|
211
vendor/github.com/davecgh/go-spew/spew/doc.go
generated
vendored
211
vendor/github.com/davecgh/go-spew/spew/doc.go
generated
vendored
|
@ -1,211 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Package spew implements a deep pretty printer for Go data structures to aid in
|
|
||||||
debugging.
|
|
||||||
|
|
||||||
A quick overview of the additional features spew provides over the built-in
|
|
||||||
printing facilities for Go data types are as follows:
|
|
||||||
|
|
||||||
* Pointers are dereferenced and followed
|
|
||||||
* Circular data structures are detected and handled properly
|
|
||||||
* Custom Stringer/error interfaces are optionally invoked, including
|
|
||||||
on unexported types
|
|
||||||
* Custom types which only implement the Stringer/error interfaces via
|
|
||||||
a pointer receiver are optionally invoked when passing non-pointer
|
|
||||||
variables
|
|
||||||
* Byte arrays and slices are dumped like the hexdump -C command which
|
|
||||||
includes offsets, byte values in hex, and ASCII output (only when using
|
|
||||||
Dump style)
|
|
||||||
|
|
||||||
There are two different approaches spew allows for dumping Go data structures:
|
|
||||||
|
|
||||||
* Dump style which prints with newlines, customizable indentation,
|
|
||||||
and additional debug information such as types and all pointer addresses
|
|
||||||
used to indirect to the final value
|
|
||||||
* A custom Formatter interface that integrates cleanly with the standard fmt
|
|
||||||
package and replaces %v, %+v, %#v, and %#+v to provide inline printing
|
|
||||||
similar to the default %v while providing the additional functionality
|
|
||||||
outlined above and passing unsupported format verbs such as %x and %q
|
|
||||||
along to fmt
|
|
||||||
|
|
||||||
Quick Start
|
|
||||||
|
|
||||||
This section demonstrates how to quickly get started with spew. See the
|
|
||||||
sections below for further details on formatting and configuration options.
|
|
||||||
|
|
||||||
To dump a variable with full newlines, indentation, type, and pointer
|
|
||||||
information use Dump, Fdump, or Sdump:
|
|
||||||
spew.Dump(myVar1, myVar2, ...)
|
|
||||||
spew.Fdump(someWriter, myVar1, myVar2, ...)
|
|
||||||
str := spew.Sdump(myVar1, myVar2, ...)
|
|
||||||
|
|
||||||
Alternatively, if you would prefer to use format strings with a compacted inline
|
|
||||||
printing style, use the convenience wrappers Printf, Fprintf, etc with
|
|
||||||
%v (most compact), %+v (adds pointer addresses), %#v (adds types), or
|
|
||||||
%#+v (adds types and pointer addresses):
|
|
||||||
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
|
||||||
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
|
||||||
spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
|
||||||
spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
|
||||||
|
|
||||||
Configuration Options
|
|
||||||
|
|
||||||
Configuration of spew is handled by fields in the ConfigState type. For
|
|
||||||
convenience, all of the top-level functions use a global state available
|
|
||||||
via the spew.Config global.
|
|
||||||
|
|
||||||
It is also possible to create a ConfigState instance that provides methods
|
|
||||||
equivalent to the top-level functions. This allows concurrent configuration
|
|
||||||
options. See the ConfigState documentation for more details.
|
|
||||||
|
|
||||||
The following configuration options are available:
|
|
||||||
* Indent
|
|
||||||
String to use for each indentation level for Dump functions.
|
|
||||||
It is a single space by default. A popular alternative is "\t".
|
|
||||||
|
|
||||||
* MaxDepth
|
|
||||||
Maximum number of levels to descend into nested data structures.
|
|
||||||
There is no limit by default.
|
|
||||||
|
|
||||||
* DisableMethods
|
|
||||||
Disables invocation of error and Stringer interface methods.
|
|
||||||
Method invocation is enabled by default.
|
|
||||||
|
|
||||||
* DisablePointerMethods
|
|
||||||
Disables invocation of error and Stringer interface methods on types
|
|
||||||
which only accept pointer receivers from non-pointer variables.
|
|
||||||
Pointer method invocation is enabled by default.
|
|
||||||
|
|
||||||
* DisablePointerAddresses
|
|
||||||
DisablePointerAddresses specifies whether to disable the printing of
|
|
||||||
pointer addresses. This is useful when diffing data structures in tests.
|
|
||||||
|
|
||||||
* DisableCapacities
|
|
||||||
DisableCapacities specifies whether to disable the printing of
|
|
||||||
capacities for arrays, slices, maps and channels. This is useful when
|
|
||||||
diffing data structures in tests.
|
|
||||||
|
|
||||||
* ContinueOnMethod
|
|
||||||
Enables recursion into types after invoking error and Stringer interface
|
|
||||||
methods. Recursion after method invocation is disabled by default.
|
|
||||||
|
|
||||||
* SortKeys
|
|
||||||
Specifies map keys should be sorted before being printed. Use
|
|
||||||
this to have a more deterministic, diffable output. Note that
|
|
||||||
only native types (bool, int, uint, floats, uintptr and string)
|
|
||||||
and types which implement error or Stringer interfaces are
|
|
||||||
supported with other types sorted according to the
|
|
||||||
reflect.Value.String() output which guarantees display
|
|
||||||
stability. Natural map order is used by default.
|
|
||||||
|
|
||||||
* SpewKeys
|
|
||||||
Specifies that, as a last resort attempt, map keys should be
|
|
||||||
spewed to strings and sorted by those strings. This is only
|
|
||||||
considered if SortKeys is true.
|
|
||||||
|
|
||||||
Dump Usage
|
|
||||||
|
|
||||||
Simply call spew.Dump with a list of variables you want to dump:
|
|
||||||
|
|
||||||
spew.Dump(myVar1, myVar2, ...)
|
|
||||||
|
|
||||||
You may also call spew.Fdump if you would prefer to output to an arbitrary
|
|
||||||
io.Writer. For example, to dump to standard error:
|
|
||||||
|
|
||||||
spew.Fdump(os.Stderr, myVar1, myVar2, ...)
|
|
||||||
|
|
||||||
A third option is to call spew.Sdump to get the formatted output as a string:
|
|
||||||
|
|
||||||
str := spew.Sdump(myVar1, myVar2, ...)
|
|
||||||
|
|
||||||
Sample Dump Output
|
|
||||||
|
|
||||||
See the Dump example for details on the setup of the types and variables being
|
|
||||||
shown here.
|
|
||||||
|
|
||||||
(main.Foo) {
|
|
||||||
unexportedField: (*main.Bar)(0xf84002e210)({
|
|
||||||
flag: (main.Flag) flagTwo,
|
|
||||||
data: (uintptr) <nil>
|
|
||||||
}),
|
|
||||||
ExportedField: (map[interface {}]interface {}) (len=1) {
|
|
||||||
(string) (len=3) "one": (bool) true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C
|
|
||||||
command as shown.
|
|
||||||
([]uint8) (len=32 cap=32) {
|
|
||||||
00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
|
|
||||||
00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
|
|
||||||
00000020 31 32 |12|
|
|
||||||
}
|
|
||||||
|
|
||||||
Custom Formatter
|
|
||||||
|
|
||||||
Spew provides a custom formatter that implements the fmt.Formatter interface
|
|
||||||
so that it integrates cleanly with standard fmt package printing functions. The
|
|
||||||
formatter is useful for inline printing of smaller data types similar to the
|
|
||||||
standard %v format specifier.
|
|
||||||
|
|
||||||
The custom formatter only responds to the %v (most compact), %+v (adds pointer
|
|
||||||
addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
|
|
||||||
combinations. Any other verbs such as %x and %q will be sent to the the
|
|
||||||
standard fmt package for formatting. In addition, the custom formatter ignores
|
|
||||||
the width and precision arguments (however they will still work on the format
|
|
||||||
specifiers not handled by the custom formatter).
|
|
||||||
|
|
||||||
Custom Formatter Usage
|
|
||||||
|
|
||||||
The simplest way to make use of the spew custom formatter is to call one of the
|
|
||||||
convenience functions such as spew.Printf, spew.Println, or spew.Printf. The
|
|
||||||
functions have syntax you are most likely already familiar with:
|
|
||||||
|
|
||||||
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
|
||||||
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
|
||||||
spew.Println(myVar, myVar2)
|
|
||||||
spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
|
||||||
spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
|
||||||
|
|
||||||
See the Index for the full list convenience functions.
|
|
||||||
|
|
||||||
Sample Formatter Output
|
|
||||||
|
|
||||||
Double pointer to a uint8:
|
|
||||||
%v: <**>5
|
|
||||||
%+v: <**>(0xf8400420d0->0xf8400420c8)5
|
|
||||||
%#v: (**uint8)5
|
|
||||||
%#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
|
|
||||||
|
|
||||||
Pointer to circular struct with a uint8 field and a pointer to itself:
|
|
||||||
%v: <*>{1 <*><shown>}
|
|
||||||
%+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>}
|
|
||||||
%#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>}
|
|
||||||
%#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>}
|
|
||||||
|
|
||||||
See the Printf example for details on the setup of variables being shown
|
|
||||||
here.
|
|
||||||
|
|
||||||
Errors
|
|
||||||
|
|
||||||
Since it is possible for custom Stringer/error interfaces to panic, spew
|
|
||||||
detects them and handles them internally by printing the panic information
|
|
||||||
inline with the output. Since spew is intended to provide deep pretty printing
|
|
||||||
capabilities on structures, it intentionally does not return any errors.
|
|
||||||
*/
|
|
||||||
package spew
|
|
509
vendor/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
509
vendor/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
|
@ -1,509 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package spew
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// uint8Type is a reflect.Type representing a uint8. It is used to
|
|
||||||
// convert cgo types to uint8 slices for hexdumping.
|
|
||||||
uint8Type = reflect.TypeOf(uint8(0))
|
|
||||||
|
|
||||||
// cCharRE is a regular expression that matches a cgo char.
|
|
||||||
// It is used to detect character arrays to hexdump them.
|
|
||||||
cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`)
|
|
||||||
|
|
||||||
// cUnsignedCharRE is a regular expression that matches a cgo unsigned
|
|
||||||
// char. It is used to detect unsigned character arrays to hexdump
|
|
||||||
// them.
|
|
||||||
cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`)
|
|
||||||
|
|
||||||
// cUint8tCharRE is a regular expression that matches a cgo uint8_t.
|
|
||||||
// It is used to detect uint8_t arrays to hexdump them.
|
|
||||||
cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// dumpState contains information about the state of a dump operation.
|
|
||||||
type dumpState struct {
|
|
||||||
w io.Writer
|
|
||||||
depth int
|
|
||||||
pointers map[uintptr]int
|
|
||||||
ignoreNextType bool
|
|
||||||
ignoreNextIndent bool
|
|
||||||
cs *ConfigState
|
|
||||||
}
|
|
||||||
|
|
||||||
// indent performs indentation according to the depth level and cs.Indent
|
|
||||||
// option.
|
|
||||||
func (d *dumpState) indent() {
|
|
||||||
if d.ignoreNextIndent {
|
|
||||||
d.ignoreNextIndent = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth))
|
|
||||||
}
|
|
||||||
|
|
||||||
// unpackValue returns values inside of non-nil interfaces when possible.
|
|
||||||
// This is useful for data types like structs, arrays, slices, and maps which
|
|
||||||
// can contain varying types packed inside an interface.
|
|
||||||
func (d *dumpState) unpackValue(v reflect.Value) reflect.Value {
|
|
||||||
if v.Kind() == reflect.Interface && !v.IsNil() {
|
|
||||||
v = v.Elem()
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// dumpPtr handles formatting of pointers by indirecting them as necessary.
|
|
||||||
func (d *dumpState) dumpPtr(v reflect.Value) {
|
|
||||||
// Remove pointers at or below the current depth from map used to detect
|
|
||||||
// circular refs.
|
|
||||||
for k, depth := range d.pointers {
|
|
||||||
if depth >= d.depth {
|
|
||||||
delete(d.pointers, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep list of all dereferenced pointers to show later.
|
|
||||||
pointerChain := make([]uintptr, 0)
|
|
||||||
|
|
||||||
// Figure out how many levels of indirection there are by dereferencing
|
|
||||||
// pointers and unpacking interfaces down the chain while detecting circular
|
|
||||||
// references.
|
|
||||||
nilFound := false
|
|
||||||
cycleFound := false
|
|
||||||
indirects := 0
|
|
||||||
ve := v
|
|
||||||
for ve.Kind() == reflect.Ptr {
|
|
||||||
if ve.IsNil() {
|
|
||||||
nilFound = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
indirects++
|
|
||||||
addr := ve.Pointer()
|
|
||||||
pointerChain = append(pointerChain, addr)
|
|
||||||
if pd, ok := d.pointers[addr]; ok && pd < d.depth {
|
|
||||||
cycleFound = true
|
|
||||||
indirects--
|
|
||||||
break
|
|
||||||
}
|
|
||||||
d.pointers[addr] = d.depth
|
|
||||||
|
|
||||||
ve = ve.Elem()
|
|
||||||
if ve.Kind() == reflect.Interface {
|
|
||||||
if ve.IsNil() {
|
|
||||||
nilFound = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
ve = ve.Elem()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display type information.
|
|
||||||
d.w.Write(openParenBytes)
|
|
||||||
d.w.Write(bytes.Repeat(asteriskBytes, indirects))
|
|
||||||
d.w.Write([]byte(ve.Type().String()))
|
|
||||||
d.w.Write(closeParenBytes)
|
|
||||||
|
|
||||||
// Display pointer information.
|
|
||||||
if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 {
|
|
||||||
d.w.Write(openParenBytes)
|
|
||||||
for i, addr := range pointerChain {
|
|
||||||
if i > 0 {
|
|
||||||
d.w.Write(pointerChainBytes)
|
|
||||||
}
|
|
||||||
printHexPtr(d.w, addr)
|
|
||||||
}
|
|
||||||
d.w.Write(closeParenBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display dereferenced value.
|
|
||||||
d.w.Write(openParenBytes)
|
|
||||||
switch {
|
|
||||||
case nilFound:
|
|
||||||
d.w.Write(nilAngleBytes)
|
|
||||||
|
|
||||||
case cycleFound:
|
|
||||||
d.w.Write(circularBytes)
|
|
||||||
|
|
||||||
default:
|
|
||||||
d.ignoreNextType = true
|
|
||||||
d.dump(ve)
|
|
||||||
}
|
|
||||||
d.w.Write(closeParenBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// dumpSlice handles formatting of arrays and slices. Byte (uint8 under
|
|
||||||
// reflection) arrays and slices are dumped in hexdump -C fashion.
|
|
||||||
func (d *dumpState) dumpSlice(v reflect.Value) {
|
|
||||||
// Determine whether this type should be hex dumped or not. Also,
|
|
||||||
// for types which should be hexdumped, try to use the underlying data
|
|
||||||
// first, then fall back to trying to convert them to a uint8 slice.
|
|
||||||
var buf []uint8
|
|
||||||
doConvert := false
|
|
||||||
doHexDump := false
|
|
||||||
numEntries := v.Len()
|
|
||||||
if numEntries > 0 {
|
|
||||||
vt := v.Index(0).Type()
|
|
||||||
vts := vt.String()
|
|
||||||
switch {
|
|
||||||
// C types that need to be converted.
|
|
||||||
case cCharRE.MatchString(vts):
|
|
||||||
fallthrough
|
|
||||||
case cUnsignedCharRE.MatchString(vts):
|
|
||||||
fallthrough
|
|
||||||
case cUint8tCharRE.MatchString(vts):
|
|
||||||
doConvert = true
|
|
||||||
|
|
||||||
// Try to use existing uint8 slices and fall back to converting
|
|
||||||
// and copying if that fails.
|
|
||||||
case vt.Kind() == reflect.Uint8:
|
|
||||||
// We need an addressable interface to convert the type
|
|
||||||
// to a byte slice. However, the reflect package won't
|
|
||||||
// give us an interface on certain things like
|
|
||||||
// unexported struct fields in order to enforce
|
|
||||||
// visibility rules. We use unsafe, when available, to
|
|
||||||
// bypass these restrictions since this package does not
|
|
||||||
// mutate the values.
|
|
||||||
vs := v
|
|
||||||
if !vs.CanInterface() || !vs.CanAddr() {
|
|
||||||
vs = unsafeReflectValue(vs)
|
|
||||||
}
|
|
||||||
if !UnsafeDisabled {
|
|
||||||
vs = vs.Slice(0, numEntries)
|
|
||||||
|
|
||||||
// Use the existing uint8 slice if it can be
|
|
||||||
// type asserted.
|
|
||||||
iface := vs.Interface()
|
|
||||||
if slice, ok := iface.([]uint8); ok {
|
|
||||||
buf = slice
|
|
||||||
doHexDump = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The underlying data needs to be converted if it can't
|
|
||||||
// be type asserted to a uint8 slice.
|
|
||||||
doConvert = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy and convert the underlying type if needed.
|
|
||||||
if doConvert && vt.ConvertibleTo(uint8Type) {
|
|
||||||
// Convert and copy each element into a uint8 byte
|
|
||||||
// slice.
|
|
||||||
buf = make([]uint8, numEntries)
|
|
||||||
for i := 0; i < numEntries; i++ {
|
|
||||||
vv := v.Index(i)
|
|
||||||
buf[i] = uint8(vv.Convert(uint8Type).Uint())
|
|
||||||
}
|
|
||||||
doHexDump = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hexdump the entire slice as needed.
|
|
||||||
if doHexDump {
|
|
||||||
indent := strings.Repeat(d.cs.Indent, d.depth)
|
|
||||||
str := indent + hex.Dump(buf)
|
|
||||||
str = strings.Replace(str, "\n", "\n"+indent, -1)
|
|
||||||
str = strings.TrimRight(str, d.cs.Indent)
|
|
||||||
d.w.Write([]byte(str))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recursively call dump for each item.
|
|
||||||
for i := 0; i < numEntries; i++ {
|
|
||||||
d.dump(d.unpackValue(v.Index(i)))
|
|
||||||
if i < (numEntries - 1) {
|
|
||||||
d.w.Write(commaNewlineBytes)
|
|
||||||
} else {
|
|
||||||
d.w.Write(newlineBytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// dump is the main workhorse for dumping a value. It uses the passed reflect
|
|
||||||
// value to figure out what kind of object we are dealing with and formats it
|
|
||||||
// appropriately. It is a recursive function, however circular data structures
|
|
||||||
// are detected and handled properly.
|
|
||||||
func (d *dumpState) dump(v reflect.Value) {
|
|
||||||
// Handle invalid reflect values immediately.
|
|
||||||
kind := v.Kind()
|
|
||||||
if kind == reflect.Invalid {
|
|
||||||
d.w.Write(invalidAngleBytes)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle pointers specially.
|
|
||||||
if kind == reflect.Ptr {
|
|
||||||
d.indent()
|
|
||||||
d.dumpPtr(v)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print type information unless already handled elsewhere.
|
|
||||||
if !d.ignoreNextType {
|
|
||||||
d.indent()
|
|
||||||
d.w.Write(openParenBytes)
|
|
||||||
d.w.Write([]byte(v.Type().String()))
|
|
||||||
d.w.Write(closeParenBytes)
|
|
||||||
d.w.Write(spaceBytes)
|
|
||||||
}
|
|
||||||
d.ignoreNextType = false
|
|
||||||
|
|
||||||
// Display length and capacity if the built-in len and cap functions
|
|
||||||
// work with the value's kind and the len/cap itself is non-zero.
|
|
||||||
valueLen, valueCap := 0, 0
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Array, reflect.Slice, reflect.Chan:
|
|
||||||
valueLen, valueCap = v.Len(), v.Cap()
|
|
||||||
case reflect.Map, reflect.String:
|
|
||||||
valueLen = v.Len()
|
|
||||||
}
|
|
||||||
if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 {
|
|
||||||
d.w.Write(openParenBytes)
|
|
||||||
if valueLen != 0 {
|
|
||||||
d.w.Write(lenEqualsBytes)
|
|
||||||
printInt(d.w, int64(valueLen), 10)
|
|
||||||
}
|
|
||||||
if !d.cs.DisableCapacities && valueCap != 0 {
|
|
||||||
if valueLen != 0 {
|
|
||||||
d.w.Write(spaceBytes)
|
|
||||||
}
|
|
||||||
d.w.Write(capEqualsBytes)
|
|
||||||
printInt(d.w, int64(valueCap), 10)
|
|
||||||
}
|
|
||||||
d.w.Write(closeParenBytes)
|
|
||||||
d.w.Write(spaceBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call Stringer/error interfaces if they exist and the handle methods flag
|
|
||||||
// is enabled
|
|
||||||
if !d.cs.DisableMethods {
|
|
||||||
if (kind != reflect.Invalid) && (kind != reflect.Interface) {
|
|
||||||
if handled := handleMethods(d.cs, d.w, v); handled {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch kind {
|
|
||||||
case reflect.Invalid:
|
|
||||||
// Do nothing. We should never get here since invalid has already
|
|
||||||
// been handled above.
|
|
||||||
|
|
||||||
case reflect.Bool:
|
|
||||||
printBool(d.w, v.Bool())
|
|
||||||
|
|
||||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
|
||||||
printInt(d.w, v.Int(), 10)
|
|
||||||
|
|
||||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
|
||||||
printUint(d.w, v.Uint(), 10)
|
|
||||||
|
|
||||||
case reflect.Float32:
|
|
||||||
printFloat(d.w, v.Float(), 32)
|
|
||||||
|
|
||||||
case reflect.Float64:
|
|
||||||
printFloat(d.w, v.Float(), 64)
|
|
||||||
|
|
||||||
case reflect.Complex64:
|
|
||||||
printComplex(d.w, v.Complex(), 32)
|
|
||||||
|
|
||||||
case reflect.Complex128:
|
|
||||||
printComplex(d.w, v.Complex(), 64)
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
if v.IsNil() {
|
|
||||||
d.w.Write(nilAngleBytes)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
fallthrough
|
|
||||||
|
|
||||||
case reflect.Array:
|
|
||||||
d.w.Write(openBraceNewlineBytes)
|
|
||||||
d.depth++
|
|
||||||
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
|
|
||||||
d.indent()
|
|
||||||
d.w.Write(maxNewlineBytes)
|
|
||||||
} else {
|
|
||||||
d.dumpSlice(v)
|
|
||||||
}
|
|
||||||
d.depth--
|
|
||||||
d.indent()
|
|
||||||
d.w.Write(closeBraceBytes)
|
|
||||||
|
|
||||||
case reflect.String:
|
|
||||||
d.w.Write([]byte(strconv.Quote(v.String())))
|
|
||||||
|
|
||||||
case reflect.Interface:
|
|
||||||
// The only time we should get here is for nil interfaces due to
|
|
||||||
// unpackValue calls.
|
|
||||||
if v.IsNil() {
|
|
||||||
d.w.Write(nilAngleBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Ptr:
|
|
||||||
// Do nothing. We should never get here since pointers have already
|
|
||||||
// been handled above.
|
|
||||||
|
|
||||||
case reflect.Map:
|
|
||||||
// nil maps should be indicated as different than empty maps
|
|
||||||
if v.IsNil() {
|
|
||||||
d.w.Write(nilAngleBytes)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
d.w.Write(openBraceNewlineBytes)
|
|
||||||
d.depth++
|
|
||||||
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
|
|
||||||
d.indent()
|
|
||||||
d.w.Write(maxNewlineBytes)
|
|
||||||
} else {
|
|
||||||
numEntries := v.Len()
|
|
||||||
keys := v.MapKeys()
|
|
||||||
if d.cs.SortKeys {
|
|
||||||
sortValues(keys, d.cs)
|
|
||||||
}
|
|
||||||
for i, key := range keys {
|
|
||||||
d.dump(d.unpackValue(key))
|
|
||||||
d.w.Write(colonSpaceBytes)
|
|
||||||
d.ignoreNextIndent = true
|
|
||||||
d.dump(d.unpackValue(v.MapIndex(key)))
|
|
||||||
if i < (numEntries - 1) {
|
|
||||||
d.w.Write(commaNewlineBytes)
|
|
||||||
} else {
|
|
||||||
d.w.Write(newlineBytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
d.depth--
|
|
||||||
d.indent()
|
|
||||||
d.w.Write(closeBraceBytes)
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
d.w.Write(openBraceNewlineBytes)
|
|
||||||
d.depth++
|
|
||||||
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
|
|
||||||
d.indent()
|
|
||||||
d.w.Write(maxNewlineBytes)
|
|
||||||
} else {
|
|
||||||
vt := v.Type()
|
|
||||||
numFields := v.NumField()
|
|
||||||
for i := 0; i < numFields; i++ {
|
|
||||||
d.indent()
|
|
||||||
vtf := vt.Field(i)
|
|
||||||
d.w.Write([]byte(vtf.Name))
|
|
||||||
d.w.Write(colonSpaceBytes)
|
|
||||||
d.ignoreNextIndent = true
|
|
||||||
d.dump(d.unpackValue(v.Field(i)))
|
|
||||||
if i < (numFields - 1) {
|
|
||||||
d.w.Write(commaNewlineBytes)
|
|
||||||
} else {
|
|
||||||
d.w.Write(newlineBytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
d.depth--
|
|
||||||
d.indent()
|
|
||||||
d.w.Write(closeBraceBytes)
|
|
||||||
|
|
||||||
case reflect.Uintptr:
|
|
||||||
printHexPtr(d.w, uintptr(v.Uint()))
|
|
||||||
|
|
||||||
case reflect.UnsafePointer, reflect.Chan, reflect.Func:
|
|
||||||
printHexPtr(d.w, v.Pointer())
|
|
||||||
|
|
||||||
// There were not any other types at the time this code was written, but
|
|
||||||
// fall back to letting the default fmt package handle it in case any new
|
|
||||||
// types are added.
|
|
||||||
default:
|
|
||||||
if v.CanInterface() {
|
|
||||||
fmt.Fprintf(d.w, "%v", v.Interface())
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(d.w, "%v", v.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fdump is a helper function to consolidate the logic from the various public
|
|
||||||
// methods which take varying writers and config states.
|
|
||||||
func fdump(cs *ConfigState, w io.Writer, a ...interface{}) {
|
|
||||||
for _, arg := range a {
|
|
||||||
if arg == nil {
|
|
||||||
w.Write(interfaceBytes)
|
|
||||||
w.Write(spaceBytes)
|
|
||||||
w.Write(nilAngleBytes)
|
|
||||||
w.Write(newlineBytes)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
d := dumpState{w: w, cs: cs}
|
|
||||||
d.pointers = make(map[uintptr]int)
|
|
||||||
d.dump(reflect.ValueOf(arg))
|
|
||||||
d.w.Write(newlineBytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fdump formats and displays the passed arguments to io.Writer w. It formats
|
|
||||||
// exactly the same as Dump.
|
|
||||||
func Fdump(w io.Writer, a ...interface{}) {
|
|
||||||
fdump(&Config, w, a...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sdump returns a string with the passed arguments formatted exactly the same
|
|
||||||
// as Dump.
|
|
||||||
func Sdump(a ...interface{}) string {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
fdump(&Config, &buf, a...)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Dump displays the passed parameters to standard out with newlines, customizable
|
|
||||||
indentation, and additional debug information such as complete types and all
|
|
||||||
pointer addresses used to indirect to the final value. It provides the
|
|
||||||
following features over the built-in printing facilities provided by the fmt
|
|
||||||
package:
|
|
||||||
|
|
||||||
* Pointers are dereferenced and followed
|
|
||||||
* Circular data structures are detected and handled properly
|
|
||||||
* Custom Stringer/error interfaces are optionally invoked, including
|
|
||||||
on unexported types
|
|
||||||
* Custom types which only implement the Stringer/error interfaces via
|
|
||||||
a pointer receiver are optionally invoked when passing non-pointer
|
|
||||||
variables
|
|
||||||
* Byte arrays and slices are dumped like the hexdump -C command which
|
|
||||||
includes offsets, byte values in hex, and ASCII output
|
|
||||||
|
|
||||||
The configuration options are controlled by an exported package global,
|
|
||||||
spew.Config. See ConfigState for options documentation.
|
|
||||||
|
|
||||||
See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
|
|
||||||
get the formatted result as a string.
|
|
||||||
*/
|
|
||||||
func Dump(a ...interface{}) {
|
|
||||||
fdump(&Config, os.Stdout, a...)
|
|
||||||
}
|
|
419
vendor/github.com/davecgh/go-spew/spew/format.go
generated
vendored
419
vendor/github.com/davecgh/go-spew/spew/format.go
generated
vendored
|
@ -1,419 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package spew
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// supportedFlags is a list of all the character flags supported by fmt package.
|
|
||||||
const supportedFlags = "0-+# "
|
|
||||||
|
|
||||||
// formatState implements the fmt.Formatter interface and contains information
|
|
||||||
// about the state of a formatting operation. The NewFormatter function can
|
|
||||||
// be used to get a new Formatter which can be used directly as arguments
|
|
||||||
// in standard fmt package printing calls.
|
|
||||||
type formatState struct {
|
|
||||||
value interface{}
|
|
||||||
fs fmt.State
|
|
||||||
depth int
|
|
||||||
pointers map[uintptr]int
|
|
||||||
ignoreNextType bool
|
|
||||||
cs *ConfigState
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildDefaultFormat recreates the original format string without precision
|
|
||||||
// and width information to pass in to fmt.Sprintf in the case of an
|
|
||||||
// unrecognized type. Unless new types are added to the language, this
|
|
||||||
// function won't ever be called.
|
|
||||||
func (f *formatState) buildDefaultFormat() (format string) {
|
|
||||||
buf := bytes.NewBuffer(percentBytes)
|
|
||||||
|
|
||||||
for _, flag := range supportedFlags {
|
|
||||||
if f.fs.Flag(int(flag)) {
|
|
||||||
buf.WriteRune(flag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.WriteRune('v')
|
|
||||||
|
|
||||||
format = buf.String()
|
|
||||||
return format
|
|
||||||
}
|
|
||||||
|
|
||||||
// constructOrigFormat recreates the original format string including precision
|
|
||||||
// and width information to pass along to the standard fmt package. This allows
|
|
||||||
// automatic deferral of all format strings this package doesn't support.
|
|
||||||
func (f *formatState) constructOrigFormat(verb rune) (format string) {
|
|
||||||
buf := bytes.NewBuffer(percentBytes)
|
|
||||||
|
|
||||||
for _, flag := range supportedFlags {
|
|
||||||
if f.fs.Flag(int(flag)) {
|
|
||||||
buf.WriteRune(flag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if width, ok := f.fs.Width(); ok {
|
|
||||||
buf.WriteString(strconv.Itoa(width))
|
|
||||||
}
|
|
||||||
|
|
||||||
if precision, ok := f.fs.Precision(); ok {
|
|
||||||
buf.Write(precisionBytes)
|
|
||||||
buf.WriteString(strconv.Itoa(precision))
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.WriteRune(verb)
|
|
||||||
|
|
||||||
format = buf.String()
|
|
||||||
return format
|
|
||||||
}
|
|
||||||
|
|
||||||
// unpackValue returns values inside of non-nil interfaces when possible and
|
|
||||||
// ensures that types for values which have been unpacked from an interface
|
|
||||||
// are displayed when the show types flag is also set.
|
|
||||||
// This is useful for data types like structs, arrays, slices, and maps which
|
|
||||||
// can contain varying types packed inside an interface.
|
|
||||||
func (f *formatState) unpackValue(v reflect.Value) reflect.Value {
|
|
||||||
if v.Kind() == reflect.Interface {
|
|
||||||
f.ignoreNextType = false
|
|
||||||
if !v.IsNil() {
|
|
||||||
v = v.Elem()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// formatPtr handles formatting of pointers by indirecting them as necessary.
|
|
||||||
func (f *formatState) formatPtr(v reflect.Value) {
|
|
||||||
// Display nil if top level pointer is nil.
|
|
||||||
showTypes := f.fs.Flag('#')
|
|
||||||
if v.IsNil() && (!showTypes || f.ignoreNextType) {
|
|
||||||
f.fs.Write(nilAngleBytes)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove pointers at or below the current depth from map used to detect
|
|
||||||
// circular refs.
|
|
||||||
for k, depth := range f.pointers {
|
|
||||||
if depth >= f.depth {
|
|
||||||
delete(f.pointers, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep list of all dereferenced pointers to possibly show later.
|
|
||||||
pointerChain := make([]uintptr, 0)
|
|
||||||
|
|
||||||
// Figure out how many levels of indirection there are by derferencing
|
|
||||||
// pointers and unpacking interfaces down the chain while detecting circular
|
|
||||||
// references.
|
|
||||||
nilFound := false
|
|
||||||
cycleFound := false
|
|
||||||
indirects := 0
|
|
||||||
ve := v
|
|
||||||
for ve.Kind() == reflect.Ptr {
|
|
||||||
if ve.IsNil() {
|
|
||||||
nilFound = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
indirects++
|
|
||||||
addr := ve.Pointer()
|
|
||||||
pointerChain = append(pointerChain, addr)
|
|
||||||
if pd, ok := f.pointers[addr]; ok && pd < f.depth {
|
|
||||||
cycleFound = true
|
|
||||||
indirects--
|
|
||||||
break
|
|
||||||
}
|
|
||||||
f.pointers[addr] = f.depth
|
|
||||||
|
|
||||||
ve = ve.Elem()
|
|
||||||
if ve.Kind() == reflect.Interface {
|
|
||||||
if ve.IsNil() {
|
|
||||||
nilFound = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
ve = ve.Elem()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display type or indirection level depending on flags.
|
|
||||||
if showTypes && !f.ignoreNextType {
|
|
||||||
f.fs.Write(openParenBytes)
|
|
||||||
f.fs.Write(bytes.Repeat(asteriskBytes, indirects))
|
|
||||||
f.fs.Write([]byte(ve.Type().String()))
|
|
||||||
f.fs.Write(closeParenBytes)
|
|
||||||
} else {
|
|
||||||
if nilFound || cycleFound {
|
|
||||||
indirects += strings.Count(ve.Type().String(), "*")
|
|
||||||
}
|
|
||||||
f.fs.Write(openAngleBytes)
|
|
||||||
f.fs.Write([]byte(strings.Repeat("*", indirects)))
|
|
||||||
f.fs.Write(closeAngleBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display pointer information depending on flags.
|
|
||||||
if f.fs.Flag('+') && (len(pointerChain) > 0) {
|
|
||||||
f.fs.Write(openParenBytes)
|
|
||||||
for i, addr := range pointerChain {
|
|
||||||
if i > 0 {
|
|
||||||
f.fs.Write(pointerChainBytes)
|
|
||||||
}
|
|
||||||
printHexPtr(f.fs, addr)
|
|
||||||
}
|
|
||||||
f.fs.Write(closeParenBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display dereferenced value.
|
|
||||||
switch {
|
|
||||||
case nilFound:
|
|
||||||
f.fs.Write(nilAngleBytes)
|
|
||||||
|
|
||||||
case cycleFound:
|
|
||||||
f.fs.Write(circularShortBytes)
|
|
||||||
|
|
||||||
default:
|
|
||||||
f.ignoreNextType = true
|
|
||||||
f.format(ve)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// format is the main workhorse for providing the Formatter interface. It
|
|
||||||
// uses the passed reflect value to figure out what kind of object we are
|
|
||||||
// dealing with and formats it appropriately. It is a recursive function,
|
|
||||||
// however circular data structures are detected and handled properly.
|
|
||||||
func (f *formatState) format(v reflect.Value) {
|
|
||||||
// Handle invalid reflect values immediately.
|
|
||||||
kind := v.Kind()
|
|
||||||
if kind == reflect.Invalid {
|
|
||||||
f.fs.Write(invalidAngleBytes)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle pointers specially.
|
|
||||||
if kind == reflect.Ptr {
|
|
||||||
f.formatPtr(v)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print type information unless already handled elsewhere.
|
|
||||||
if !f.ignoreNextType && f.fs.Flag('#') {
|
|
||||||
f.fs.Write(openParenBytes)
|
|
||||||
f.fs.Write([]byte(v.Type().String()))
|
|
||||||
f.fs.Write(closeParenBytes)
|
|
||||||
}
|
|
||||||
f.ignoreNextType = false
|
|
||||||
|
|
||||||
// Call Stringer/error interfaces if they exist and the handle methods
|
|
||||||
// flag is enabled.
|
|
||||||
if !f.cs.DisableMethods {
|
|
||||||
if (kind != reflect.Invalid) && (kind != reflect.Interface) {
|
|
||||||
if handled := handleMethods(f.cs, f.fs, v); handled {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch kind {
|
|
||||||
case reflect.Invalid:
|
|
||||||
// Do nothing. We should never get here since invalid has already
|
|
||||||
// been handled above.
|
|
||||||
|
|
||||||
case reflect.Bool:
|
|
||||||
printBool(f.fs, v.Bool())
|
|
||||||
|
|
||||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
|
||||||
printInt(f.fs, v.Int(), 10)
|
|
||||||
|
|
||||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
|
||||||
printUint(f.fs, v.Uint(), 10)
|
|
||||||
|
|
||||||
case reflect.Float32:
|
|
||||||
printFloat(f.fs, v.Float(), 32)
|
|
||||||
|
|
||||||
case reflect.Float64:
|
|
||||||
printFloat(f.fs, v.Float(), 64)
|
|
||||||
|
|
||||||
case reflect.Complex64:
|
|
||||||
printComplex(f.fs, v.Complex(), 32)
|
|
||||||
|
|
||||||
case reflect.Complex128:
|
|
||||||
printComplex(f.fs, v.Complex(), 64)
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
if v.IsNil() {
|
|
||||||
f.fs.Write(nilAngleBytes)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
fallthrough
|
|
||||||
|
|
||||||
case reflect.Array:
|
|
||||||
f.fs.Write(openBracketBytes)
|
|
||||||
f.depth++
|
|
||||||
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
|
|
||||||
f.fs.Write(maxShortBytes)
|
|
||||||
} else {
|
|
||||||
numEntries := v.Len()
|
|
||||||
for i := 0; i < numEntries; i++ {
|
|
||||||
if i > 0 {
|
|
||||||
f.fs.Write(spaceBytes)
|
|
||||||
}
|
|
||||||
f.ignoreNextType = true
|
|
||||||
f.format(f.unpackValue(v.Index(i)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f.depth--
|
|
||||||
f.fs.Write(closeBracketBytes)
|
|
||||||
|
|
||||||
case reflect.String:
|
|
||||||
f.fs.Write([]byte(v.String()))
|
|
||||||
|
|
||||||
case reflect.Interface:
|
|
||||||
// The only time we should get here is for nil interfaces due to
|
|
||||||
// unpackValue calls.
|
|
||||||
if v.IsNil() {
|
|
||||||
f.fs.Write(nilAngleBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Ptr:
|
|
||||||
// Do nothing. We should never get here since pointers have already
|
|
||||||
// been handled above.
|
|
||||||
|
|
||||||
case reflect.Map:
|
|
||||||
// nil maps should be indicated as different than empty maps
|
|
||||||
if v.IsNil() {
|
|
||||||
f.fs.Write(nilAngleBytes)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
f.fs.Write(openMapBytes)
|
|
||||||
f.depth++
|
|
||||||
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
|
|
||||||
f.fs.Write(maxShortBytes)
|
|
||||||
} else {
|
|
||||||
keys := v.MapKeys()
|
|
||||||
if f.cs.SortKeys {
|
|
||||||
sortValues(keys, f.cs)
|
|
||||||
}
|
|
||||||
for i, key := range keys {
|
|
||||||
if i > 0 {
|
|
||||||
f.fs.Write(spaceBytes)
|
|
||||||
}
|
|
||||||
f.ignoreNextType = true
|
|
||||||
f.format(f.unpackValue(key))
|
|
||||||
f.fs.Write(colonBytes)
|
|
||||||
f.ignoreNextType = true
|
|
||||||
f.format(f.unpackValue(v.MapIndex(key)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f.depth--
|
|
||||||
f.fs.Write(closeMapBytes)
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
numFields := v.NumField()
|
|
||||||
f.fs.Write(openBraceBytes)
|
|
||||||
f.depth++
|
|
||||||
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
|
|
||||||
f.fs.Write(maxShortBytes)
|
|
||||||
} else {
|
|
||||||
vt := v.Type()
|
|
||||||
for i := 0; i < numFields; i++ {
|
|
||||||
if i > 0 {
|
|
||||||
f.fs.Write(spaceBytes)
|
|
||||||
}
|
|
||||||
vtf := vt.Field(i)
|
|
||||||
if f.fs.Flag('+') || f.fs.Flag('#') {
|
|
||||||
f.fs.Write([]byte(vtf.Name))
|
|
||||||
f.fs.Write(colonBytes)
|
|
||||||
}
|
|
||||||
f.format(f.unpackValue(v.Field(i)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f.depth--
|
|
||||||
f.fs.Write(closeBraceBytes)
|
|
||||||
|
|
||||||
case reflect.Uintptr:
|
|
||||||
printHexPtr(f.fs, uintptr(v.Uint()))
|
|
||||||
|
|
||||||
case reflect.UnsafePointer, reflect.Chan, reflect.Func:
|
|
||||||
printHexPtr(f.fs, v.Pointer())
|
|
||||||
|
|
||||||
// There were not any other types at the time this code was written, but
|
|
||||||
// fall back to letting the default fmt package handle it if any get added.
|
|
||||||
default:
|
|
||||||
format := f.buildDefaultFormat()
|
|
||||||
if v.CanInterface() {
|
|
||||||
fmt.Fprintf(f.fs, format, v.Interface())
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(f.fs, format, v.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format satisfies the fmt.Formatter interface. See NewFormatter for usage
|
|
||||||
// details.
|
|
||||||
func (f *formatState) Format(fs fmt.State, verb rune) {
|
|
||||||
f.fs = fs
|
|
||||||
|
|
||||||
// Use standard formatting for verbs that are not v.
|
|
||||||
if verb != 'v' {
|
|
||||||
format := f.constructOrigFormat(verb)
|
|
||||||
fmt.Fprintf(fs, format, f.value)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.value == nil {
|
|
||||||
if fs.Flag('#') {
|
|
||||||
fs.Write(interfaceBytes)
|
|
||||||
}
|
|
||||||
fs.Write(nilAngleBytes)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
f.format(reflect.ValueOf(f.value))
|
|
||||||
}
|
|
||||||
|
|
||||||
// newFormatter is a helper function to consolidate the logic from the various
|
|
||||||
// public methods which take varying config states.
|
|
||||||
func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter {
|
|
||||||
fs := &formatState{value: v, cs: cs}
|
|
||||||
fs.pointers = make(map[uintptr]int)
|
|
||||||
return fs
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
NewFormatter returns a custom formatter that satisfies the fmt.Formatter
|
|
||||||
interface. As a result, it integrates cleanly with standard fmt package
|
|
||||||
printing functions. The formatter is useful for inline printing of smaller data
|
|
||||||
types similar to the standard %v format specifier.
|
|
||||||
|
|
||||||
The custom formatter only responds to the %v (most compact), %+v (adds pointer
|
|
||||||
addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
|
|
||||||
combinations. Any other verbs such as %x and %q will be sent to the the
|
|
||||||
standard fmt package for formatting. In addition, the custom formatter ignores
|
|
||||||
the width and precision arguments (however they will still work on the format
|
|
||||||
specifiers not handled by the custom formatter).
|
|
||||||
|
|
||||||
Typically this function shouldn't be called directly. It is much easier to make
|
|
||||||
use of the custom formatter by calling one of the convenience functions such as
|
|
||||||
Printf, Println, or Fprintf.
|
|
||||||
*/
|
|
||||||
func NewFormatter(v interface{}) fmt.Formatter {
|
|
||||||
return newFormatter(&Config, v)
|
|
||||||
}
|
|
148
vendor/github.com/davecgh/go-spew/spew/spew.go
generated
vendored
148
vendor/github.com/davecgh/go-spew/spew/spew.go
generated
vendored
|
@ -1,148 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package spew
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
|
|
||||||
// passed with a default Formatter interface returned by NewFormatter. It
|
|
||||||
// returns the formatted string as a value that satisfies error. See
|
|
||||||
// NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b))
|
|
||||||
func Errorf(format string, a ...interface{}) (err error) {
|
|
||||||
return fmt.Errorf(format, convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
|
|
||||||
// passed with a default Formatter interface returned by NewFormatter. It
|
|
||||||
// returns the number of bytes written and any write error encountered. See
|
|
||||||
// NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b))
|
|
||||||
func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
|
|
||||||
return fmt.Fprint(w, convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
|
|
||||||
// passed with a default Formatter interface returned by NewFormatter. It
|
|
||||||
// returns the number of bytes written and any write error encountered. See
|
|
||||||
// NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b))
|
|
||||||
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
|
|
||||||
return fmt.Fprintf(w, format, convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
|
|
||||||
// passed with a default Formatter interface returned by NewFormatter. See
|
|
||||||
// NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b))
|
|
||||||
func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
|
|
||||||
return fmt.Fprintln(w, convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print is a wrapper for fmt.Print that treats each argument as if it were
|
|
||||||
// passed with a default Formatter interface returned by NewFormatter. It
|
|
||||||
// returns the number of bytes written and any write error encountered. See
|
|
||||||
// NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b))
|
|
||||||
func Print(a ...interface{}) (n int, err error) {
|
|
||||||
return fmt.Print(convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Printf is a wrapper for fmt.Printf that treats each argument as if it were
|
|
||||||
// passed with a default Formatter interface returned by NewFormatter. It
|
|
||||||
// returns the number of bytes written and any write error encountered. See
|
|
||||||
// NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b))
|
|
||||||
func Printf(format string, a ...interface{}) (n int, err error) {
|
|
||||||
return fmt.Printf(format, convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Println is a wrapper for fmt.Println that treats each argument as if it were
|
|
||||||
// passed with a default Formatter interface returned by NewFormatter. It
|
|
||||||
// returns the number of bytes written and any write error encountered. See
|
|
||||||
// NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b))
|
|
||||||
func Println(a ...interface{}) (n int, err error) {
|
|
||||||
return fmt.Println(convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
|
|
||||||
// passed with a default Formatter interface returned by NewFormatter. It
|
|
||||||
// returns the resulting string. See NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b))
|
|
||||||
func Sprint(a ...interface{}) string {
|
|
||||||
return fmt.Sprint(convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
|
|
||||||
// passed with a default Formatter interface returned by NewFormatter. It
|
|
||||||
// returns the resulting string. See NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b))
|
|
||||||
func Sprintf(format string, a ...interface{}) string {
|
|
||||||
return fmt.Sprintf(format, convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
|
|
||||||
// were passed with a default Formatter interface returned by NewFormatter. It
|
|
||||||
// returns the resulting string. See NewFormatter for formatting details.
|
|
||||||
//
|
|
||||||
// This function is shorthand for the following syntax:
|
|
||||||
//
|
|
||||||
// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b))
|
|
||||||
func Sprintln(a ...interface{}) string {
|
|
||||||
return fmt.Sprintln(convertArgs(a)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertArgs accepts a slice of arguments and returns a slice of the same
|
|
||||||
// length with each argument converted to a default spew Formatter interface.
|
|
||||||
func convertArgs(args []interface{}) (formatters []interface{}) {
|
|
||||||
formatters = make([]interface{}, len(args))
|
|
||||||
for index, arg := range args {
|
|
||||||
formatters[index] = NewFormatter(arg)
|
|
||||||
}
|
|
||||||
return formatters
|
|
||||||
}
|
|
3
vendor/github.com/sirupsen/logrus/.gitignore
generated
vendored
3
vendor/github.com/sirupsen/logrus/.gitignore
generated
vendored
|
@ -1,4 +1 @@
|
||||||
logrus
|
logrus
|
||||||
vendor
|
|
||||||
|
|
||||||
.idea/
|
|
||||||
|
|
40
vendor/github.com/sirupsen/logrus/.golangci.yml
generated
vendored
40
vendor/github.com/sirupsen/logrus/.golangci.yml
generated
vendored
|
@ -1,40 +0,0 @@
|
||||||
run:
|
|
||||||
# do not run on test files yet
|
|
||||||
tests: false
|
|
||||||
|
|
||||||
# all available settings of specific linters
|
|
||||||
linters-settings:
|
|
||||||
errcheck:
|
|
||||||
# report about not checking of errors in type assetions: `a := b.(MyStruct)`;
|
|
||||||
# default is false: such cases aren't reported by default.
|
|
||||||
check-type-assertions: false
|
|
||||||
|
|
||||||
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
|
|
||||||
# default is false: such cases aren't reported by default.
|
|
||||||
check-blank: false
|
|
||||||
|
|
||||||
lll:
|
|
||||||
line-length: 100
|
|
||||||
tab-width: 4
|
|
||||||
|
|
||||||
prealloc:
|
|
||||||
simple: false
|
|
||||||
range-loops: false
|
|
||||||
for-loops: false
|
|
||||||
|
|
||||||
whitespace:
|
|
||||||
multi-if: false # Enforces newlines (or comments) after every multi-line if statement
|
|
||||||
multi-func: false # Enforces newlines (or comments) after every multi-line function signature
|
|
||||||
|
|
||||||
linters:
|
|
||||||
enable:
|
|
||||||
- megacheck
|
|
||||||
- govet
|
|
||||||
disable:
|
|
||||||
- maligned
|
|
||||||
- prealloc
|
|
||||||
disable-all: false
|
|
||||||
presets:
|
|
||||||
- bugs
|
|
||||||
- unused
|
|
||||||
fast: false
|
|
22
vendor/github.com/sirupsen/logrus/.travis.yml
generated
vendored
22
vendor/github.com/sirupsen/logrus/.travis.yml
generated
vendored
|
@ -1,17 +1,15 @@
|
||||||
language: go
|
language: go
|
||||||
go_import_path: github.com/sirupsen/logrus
|
go:
|
||||||
git:
|
- 1.6.x
|
||||||
depth: 1
|
- 1.7.x
|
||||||
|
- 1.8.x
|
||||||
|
- tip
|
||||||
env:
|
env:
|
||||||
- GO111MODULE=on
|
- GOMAXPROCS=4 GORACE=halt_on_error=1
|
||||||
go: [1.13.x, 1.14.x]
|
|
||||||
os: [linux, osx]
|
|
||||||
install:
|
install:
|
||||||
- ./travis/install.sh
|
- go get github.com/stretchr/testify/assert
|
||||||
|
- go get gopkg.in/gemnasium/logrus-airbrake-hook.v2
|
||||||
|
- go get golang.org/x/sys/unix
|
||||||
|
- go get golang.org/x/sys/windows
|
||||||
script:
|
script:
|
||||||
- ./travis/cross_build.sh
|
|
||||||
- ./travis/lint.sh
|
|
||||||
- export GOMAXPROCS=4
|
|
||||||
- export GORACE=halt_on_error=1
|
|
||||||
- go test -race -v ./...
|
- go test -race -v ./...
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then go test -race -v -tags appengine ./... ; fi
|
|
||||||
|
|
110
vendor/github.com/sirupsen/logrus/CHANGELOG.md
generated
vendored
110
vendor/github.com/sirupsen/logrus/CHANGELOG.md
generated
vendored
|
@ -1,113 +1,3 @@
|
||||||
# 1.6.0
|
|
||||||
Fixes:
|
|
||||||
* end of line cleanup
|
|
||||||
* revert the entry concurrency bug fix whic leads to deadlock under some circumstances
|
|
||||||
* update dependency on go-windows-terminal-sequences to fix a crash with go 1.14
|
|
||||||
|
|
||||||
Features:
|
|
||||||
* add an option to the `TextFormatter` to completely disable fields quoting
|
|
||||||
|
|
||||||
# 1.5.0
|
|
||||||
Code quality:
|
|
||||||
* add golangci linter run on travis
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
* add mutex for hooks concurrent access on `Entry` data
|
|
||||||
* caller function field for go1.14
|
|
||||||
* fix build issue for gopherjs target
|
|
||||||
|
|
||||||
Feature:
|
|
||||||
* add an hooks/writer sub-package whose goal is to split output on different stream depending on the trace level
|
|
||||||
* add a `DisableHTMLEscape` option in the `JSONFormatter`
|
|
||||||
* add `ForceQuote` and `PadLevelText` options in the `TextFormatter`
|
|
||||||
|
|
||||||
# 1.4.2
|
|
||||||
* Fixes build break for plan9, nacl, solaris
|
|
||||||
# 1.4.1
|
|
||||||
This new release introduces:
|
|
||||||
* Enhance TextFormatter to not print caller information when they are empty (#944)
|
|
||||||
* Remove dependency on golang.org/x/crypto (#932, #943)
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
* Fix Entry.WithContext method to return a copy of the initial entry (#941)
|
|
||||||
|
|
||||||
# 1.4.0
|
|
||||||
This new release introduces:
|
|
||||||
* Add `DeferExitHandler`, similar to `RegisterExitHandler` but prepending the handler to the list of handlers (semantically like `defer`) (#848).
|
|
||||||
* Add `CallerPrettyfier` to `JSONFormatter` and `TextFormatter` (#909, #911)
|
|
||||||
* Add `Entry.WithContext()` and `Entry.Context`, to set a context on entries to be used e.g. in hooks (#919).
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
* Fix wrong method calls `Logger.Print` and `Logger.Warningln` (#893).
|
|
||||||
* Update `Entry.Logf` to not do string formatting unless the log level is enabled (#903)
|
|
||||||
* Fix infinite recursion on unknown `Level.String()` (#907)
|
|
||||||
* Fix race condition in `getCaller` (#916).
|
|
||||||
|
|
||||||
|
|
||||||
# 1.3.0
|
|
||||||
This new release introduces:
|
|
||||||
* Log, Logf, Logln functions for Logger and Entry that take a Level
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
* Building prometheus node_exporter on AIX (#840)
|
|
||||||
* Race condition in TextFormatter (#468)
|
|
||||||
* Travis CI import path (#868)
|
|
||||||
* Remove coloured output on Windows (#862)
|
|
||||||
* Pointer to func as field in JSONFormatter (#870)
|
|
||||||
* Properly marshal Levels (#873)
|
|
||||||
|
|
||||||
# 1.2.0
|
|
||||||
This new release introduces:
|
|
||||||
* A new method `SetReportCaller` in the `Logger` to enable the file, line and calling function from which the trace has been issued
|
|
||||||
* A new trace level named `Trace` whose level is below `Debug`
|
|
||||||
* A configurable exit function to be called upon a Fatal trace
|
|
||||||
* The `Level` object now implements `encoding.TextUnmarshaler` interface
|
|
||||||
|
|
||||||
# 1.1.1
|
|
||||||
This is a bug fix release.
|
|
||||||
* fix the build break on Solaris
|
|
||||||
* don't drop a whole trace in JSONFormatter when a field param is a function pointer which can not be serialized
|
|
||||||
|
|
||||||
# 1.1.0
|
|
||||||
This new release introduces:
|
|
||||||
* several fixes:
|
|
||||||
* a fix for a race condition on entry formatting
|
|
||||||
* proper cleanup of previously used entries before putting them back in the pool
|
|
||||||
* the extra new line at the end of message in text formatter has been removed
|
|
||||||
* a new global public API to check if a level is activated: IsLevelEnabled
|
|
||||||
* the following methods have been added to the Logger object
|
|
||||||
* IsLevelEnabled
|
|
||||||
* SetFormatter
|
|
||||||
* SetOutput
|
|
||||||
* ReplaceHooks
|
|
||||||
* introduction of go module
|
|
||||||
* an indent configuration for the json formatter
|
|
||||||
* output colour support for windows
|
|
||||||
* the field sort function is now configurable for text formatter
|
|
||||||
* the CLICOLOR and CLICOLOR\_FORCE environment variable support in text formater
|
|
||||||
|
|
||||||
# 1.0.6
|
|
||||||
|
|
||||||
This new release introduces:
|
|
||||||
* a new api WithTime which allows to easily force the time of the log entry
|
|
||||||
which is mostly useful for logger wrapper
|
|
||||||
* a fix reverting the immutability of the entry given as parameter to the hooks
|
|
||||||
a new configuration field of the json formatter in order to put all the fields
|
|
||||||
in a nested dictionnary
|
|
||||||
* a new SetOutput method in the Logger
|
|
||||||
* a new configuration of the textformatter to configure the name of the default keys
|
|
||||||
* a new configuration of the text formatter to disable the level truncation
|
|
||||||
|
|
||||||
# 1.0.5
|
|
||||||
|
|
||||||
* Fix hooks race (#707)
|
|
||||||
* Fix panic deadlock (#695)
|
|
||||||
|
|
||||||
# 1.0.4
|
|
||||||
|
|
||||||
* Fix race when adding hooks (#612)
|
|
||||||
* Fix terminal check in AppEngine (#635)
|
|
||||||
|
|
||||||
# 1.0.3
|
# 1.0.3
|
||||||
|
|
||||||
* Replace example files with testable examples
|
* Replace example files with testable examples
|
||||||
|
|
138
vendor/github.com/sirupsen/logrus/README.md
generated
vendored
138
vendor/github.com/sirupsen/logrus/README.md
generated
vendored
|
@ -1,28 +1,8 @@
|
||||||
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/> [![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](https://godoc.org/github.com/sirupsen/logrus)
|
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/> [![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](https://godoc.org/github.com/sirupsen/logrus)
|
||||||
|
|
||||||
Logrus is a structured logger for Go (golang), completely API compatible with
|
Logrus is a structured logger for Go (golang), completely API compatible with
|
||||||
the standard library logger.
|
the standard library logger.
|
||||||
|
|
||||||
**Logrus is in maintenance-mode.** We will not be introducing new features. It's
|
|
||||||
simply too hard to do in a way that won't break many people's projects, which is
|
|
||||||
the last thing you want from your Logging library (again...).
|
|
||||||
|
|
||||||
This does not mean Logrus is dead. Logrus will continue to be maintained for
|
|
||||||
security, (backwards compatible) bug fixes, and performance (where we are
|
|
||||||
limited by the interface).
|
|
||||||
|
|
||||||
I believe Logrus' biggest contribution is to have played a part in today's
|
|
||||||
widespread use of structured logging in Golang. There doesn't seem to be a
|
|
||||||
reason to do a major, breaking iteration into Logrus V2, since the fantastic Go
|
|
||||||
community has built those independently. Many fantastic alternatives have sprung
|
|
||||||
up. Logrus would look like those, had it been re-designed with what we know
|
|
||||||
about structured logging in Go today. Check out, for example,
|
|
||||||
[Zerolog][zerolog], [Zap][zap], and [Apex][apex].
|
|
||||||
|
|
||||||
[zerolog]: https://github.com/rs/zerolog
|
|
||||||
[zap]: https://github.com/uber-go/zap
|
|
||||||
[apex]: https://github.com/apex/log
|
|
||||||
|
|
||||||
**Seeing weird case-sensitive problems?** It's in the past been possible to
|
**Seeing weird case-sensitive problems?** It's in the past been possible to
|
||||||
import Logrus as both upper- and lower-case. Due to the Go package environment,
|
import Logrus as both upper- and lower-case. Due to the Go package environment,
|
||||||
this caused issues in the community and we needed a standard. Some environments
|
this caused issues in the community and we needed a standard. Some environments
|
||||||
|
@ -35,6 +15,11 @@ comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437).
|
||||||
For an in-depth explanation of the casing issue, see [this
|
For an in-depth explanation of the casing issue, see [this
|
||||||
comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276).
|
comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276).
|
||||||
|
|
||||||
|
**Are you interested in assisting in maintaining Logrus?** Currently I have a
|
||||||
|
lot of obligations, and I am unable to provide Logrus with the maintainership it
|
||||||
|
needs. If you'd like to help, please reach out to me at `simon at author's
|
||||||
|
username dot com`.
|
||||||
|
|
||||||
Nicely color-coded in development (when a TTY is attached, otherwise just
|
Nicely color-coded in development (when a TTY is attached, otherwise just
|
||||||
plain text):
|
plain text):
|
||||||
|
|
||||||
|
@ -71,39 +56,8 @@ time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased
|
||||||
time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
|
time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
|
||||||
time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009
|
time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009
|
||||||
time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true
|
time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true
|
||||||
|
exit status 1
|
||||||
```
|
```
|
||||||
To ensure this behaviour even if a TTY is attached, set your formatter as follows:
|
|
||||||
|
|
||||||
```go
|
|
||||||
log.SetFormatter(&log.TextFormatter{
|
|
||||||
DisableColors: true,
|
|
||||||
FullTimestamp: true,
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Logging Method Name
|
|
||||||
|
|
||||||
If you wish to add the calling method as a field, instruct the logger via:
|
|
||||||
```go
|
|
||||||
log.SetReportCaller(true)
|
|
||||||
```
|
|
||||||
This adds the caller as 'method' like so:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by",
|
|
||||||
"time":"2014-03-10 19:57:38.562543129 -0400 EDT"}
|
|
||||||
```
|
|
||||||
|
|
||||||
```text
|
|
||||||
time="2015-03-26T01:27:38-04:00" level=fatal method=github.com/sirupsen/arcticcreatures.migrate msg="a penguin swims by" animal=penguin
|
|
||||||
```
|
|
||||||
Note that this does add measurable overhead - the cost will depend on the version of Go, but is
|
|
||||||
between 20 and 40% in recent tests with 1.6 and 1.7. You can validate this in your
|
|
||||||
environment via benchmarks:
|
|
||||||
```
|
|
||||||
go test -bench=.*CallerTracing
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### Case-sensitivity
|
#### Case-sensitivity
|
||||||
|
|
||||||
|
@ -202,7 +156,7 @@ func main() {
|
||||||
log.Out = os.Stdout
|
log.Out = os.Stdout
|
||||||
|
|
||||||
// You could set this to any `io.Writer` such as a file
|
// You could set this to any `io.Writer` such as a file
|
||||||
// file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
// file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666)
|
||||||
// if err == nil {
|
// if err == nil {
|
||||||
// log.Out = file
|
// log.Out = file
|
||||||
// } else {
|
// } else {
|
||||||
|
@ -266,7 +220,7 @@ Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake"
|
"gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake"
|
||||||
logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
|
logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
|
||||||
"log/syslog"
|
"log/syslog"
|
||||||
)
|
)
|
||||||
|
@ -287,15 +241,60 @@ func init() {
|
||||||
```
|
```
|
||||||
Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md).
|
Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md).
|
||||||
|
|
||||||
A list of currently known service hooks can be found in this wiki [page](https://github.com/sirupsen/logrus/wiki/Hooks)
|
| Hook | Description |
|
||||||
|
| ----- | ----------- |
|
||||||
|
| [Airbrake "legacy"](https://github.com/gemnasium/logrus-airbrake-legacy-hook) | Send errors to an exception tracking service compatible with the Airbrake API V2. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. |
|
||||||
|
| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. |
|
||||||
|
| [Amazon Kinesis](https://github.com/evalphobia/logrus_kinesis) | Hook for logging to [Amazon Kinesis](https://aws.amazon.com/kinesis/) |
|
||||||
|
| [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) |
|
||||||
|
| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. |
|
||||||
|
| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic |
|
||||||
|
| [Discordrus](https://github.com/kz/discordrus) | Hook for logging to [Discord](https://discordapp.com/) |
|
||||||
|
| [ElasticSearch](https://github.com/sohlich/elogrus) | Hook for logging to ElasticSearch|
|
||||||
|
| [Firehose](https://github.com/beaubrewer/logrus_firehose) | Hook for logging to [Amazon Firehose](https://aws.amazon.com/kinesis/firehose/)
|
||||||
|
| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd |
|
||||||
|
| [Go-Slack](https://github.com/multiplay/go-slack) | Hook for logging to [Slack](https://slack.com) |
|
||||||
|
| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) |
|
||||||
|
| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. |
|
||||||
|
| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger |
|
||||||
|
| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb |
|
||||||
|
| [Influxus](http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB](http://influxdata.com/) |
|
||||||
|
| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` |
|
||||||
|
| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka |
|
||||||
|
| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem |
|
||||||
|
| [Logentries](https://github.com/jcftang/logentriesrus) | Hook for logging to [Logentries](https://logentries.com/) |
|
||||||
|
| [Logentrus](https://github.com/puddingfactory/logentrus) | Hook for logging to [Logentries](https://logentries.com/) |
|
||||||
|
| [Logmatic.io](https://github.com/logmatic/logmatic-go) | Hook for logging to [Logmatic.io](http://logmatic.io/) |
|
||||||
|
| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) |
|
||||||
|
| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) |
|
||||||
|
| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail |
|
||||||
|
| [Mattermost](https://github.com/shuLhan/mattermost-integration/tree/master/hooks/logrus) | Hook for logging to [Mattermost](https://mattermost.com/) |
|
||||||
|
| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb |
|
||||||
|
| [NATS-Hook](https://github.com/rybit/nats_logrus_hook) | Hook for logging to [NATS](https://nats.io) |
|
||||||
|
| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit |
|
||||||
|
| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. |
|
||||||
|
| [PostgreSQL](https://github.com/gemnasium/logrus-postgresql-hook) | Send logs to [PostgreSQL](http://postgresql.org) |
|
||||||
|
| [Pushover](https://github.com/toorop/logrus_pushover) | Send error via [Pushover](https://pushover.net) |
|
||||||
|
| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) |
|
||||||
|
| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) |
|
||||||
|
| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar |
|
||||||
|
| [Scribe](https://github.com/sagar8192/logrus-scribe-hook) | Hook for logging to [Scribe](https://github.com/facebookarchive/scribe)|
|
||||||
|
| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. |
|
||||||
|
| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. |
|
||||||
|
| [Stackdriver](https://github.com/knq/sdhook) | Hook for logging to [Google Stackdriver](https://cloud.google.com/logging/) |
|
||||||
|
| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)|
|
||||||
|
| [Syslog](https://github.com/sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. |
|
||||||
|
| [Syslog TLS](https://github.com/shinji62/logrus-syslog-ng) | Send errors to remote syslog server with TLS support. |
|
||||||
|
| [TraceView](https://github.com/evalphobia/logrus_appneta) | Hook for logging to [AppNeta TraceView](https://www.appneta.com/products/traceview/) |
|
||||||
|
| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) |
|
||||||
|
| [logz.io](https://github.com/ripcurld00d/logrus-logzio-hook) | Hook for logging to [logz.io](https://logz.io), a Log as a Service using Logstash |
|
||||||
|
| [SQS-Hook](https://github.com/tsarpaul/logrus_sqs) | Hook for logging to [Amazon Simple Queue Service (SQS)](https://aws.amazon.com/sqs/) |
|
||||||
|
|
||||||
#### Level logging
|
#### Level logging
|
||||||
|
|
||||||
Logrus has seven logging levels: Trace, Debug, Info, Warning, Error, Fatal and Panic.
|
Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
log.Trace("Something very low level.")
|
|
||||||
log.Debug("Useful debugging information.")
|
log.Debug("Useful debugging information.")
|
||||||
log.Info("Something noteworthy happened!")
|
log.Info("Something noteworthy happened!")
|
||||||
log.Warn("You should probably take a look at this.")
|
log.Warn("You should probably take a look at this.")
|
||||||
|
@ -367,23 +366,16 @@ The built-in logging formatters are:
|
||||||
field to `true`. To force no colored output even if there is a TTY set the
|
field to `true`. To force no colored output even if there is a TTY set the
|
||||||
`DisableColors` field to `true`. For Windows, see
|
`DisableColors` field to `true`. For Windows, see
|
||||||
[github.com/mattn/go-colorable](https://github.com/mattn/go-colorable).
|
[github.com/mattn/go-colorable](https://github.com/mattn/go-colorable).
|
||||||
* When colors are enabled, levels are truncated to 4 characters by default. To disable
|
|
||||||
truncation set the `DisableLevelTruncation` field to `true`.
|
|
||||||
* When outputting to a TTY, it's often helpful to visually scan down a column where all the levels are the same width. Setting the `PadLevelText` field to `true` enables this behavior, by adding padding to the level text.
|
|
||||||
* All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter).
|
* All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter).
|
||||||
* `logrus.JSONFormatter`. Logs fields as JSON.
|
* `logrus.JSONFormatter`. Logs fields as JSON.
|
||||||
* All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter).
|
* All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter).
|
||||||
|
|
||||||
Third party logging formatters:
|
Third party logging formatters:
|
||||||
|
|
||||||
* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can be parsed by Kubernetes and Google Container Engine.
|
* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can by parsed by Kubernetes and Google Container Engine.
|
||||||
* [`GELF`](https://github.com/fabienm/go-logrus-formatters). Formats entries so they comply to Graylog's [GELF 1.1 specification](http://docs.graylog.org/en/2.4/pages/gelf.html).
|
|
||||||
* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
|
* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
|
||||||
* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
|
* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
|
||||||
* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the Power of Zalgo.
|
* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
|
||||||
* [`nested-logrus-formatter`](https://github.com/antonfisher/nested-logrus-formatter). Converts logrus fields to a nested structure.
|
|
||||||
* [`powerful-logrus-formatter`](https://github.com/zput/zxcTool). get fileName, log's line number and the latest function's name when print log; Sava log to files.
|
|
||||||
* [`caption-json-formatter`](https://github.com/nolleh/caption_json_formatter). logrus's message json formatter with human-readable caption added.
|
|
||||||
|
|
||||||
You can define your formatter by implementing the `Formatter` interface,
|
You can define your formatter by implementing the `Formatter` interface,
|
||||||
requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
|
requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
|
||||||
|
@ -448,14 +440,14 @@ entries. It should not be a feature of the application-level logger.
|
||||||
|
|
||||||
| Tool | Description |
|
| Tool | Description |
|
||||||
| ---- | ----------- |
|
| ---- | ----------- |
|
||||||
|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will be generated with different configs in different environments.|
|
|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.|
|
||||||
|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) |
|
|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) |
|
||||||
|
|
||||||
#### Testing
|
#### Testing
|
||||||
|
|
||||||
Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides:
|
Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides:
|
||||||
|
|
||||||
* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just adds the `test` hook
|
* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just add the `test` hook
|
||||||
* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any):
|
* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any):
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
@ -483,7 +475,7 @@ func TestSomething(t*testing.T){
|
||||||
|
|
||||||
Logrus can register one or more functions that will be called when any `fatal`
|
Logrus can register one or more functions that will be called when any `fatal`
|
||||||
level message is logged. The registered handlers will be executed before
|
level message is logged. The registered handlers will be executed before
|
||||||
logrus performs an `os.Exit(1)`. This behavior may be helpful if callers need
|
logrus performs a `os.Exit(1)`. This behavior may be helpful if callers need
|
||||||
to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted.
|
to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -497,7 +489,7 @@ logrus.RegisterExitHandler(handler)
|
||||||
|
|
||||||
#### Thread safety
|
#### Thread safety
|
||||||
|
|
||||||
By default, Logger is protected by a mutex for concurrent writes. The mutex is held when calling hooks and writing logs.
|
By default Logger is protected by mutex for concurrent writes, this mutex is invoked when calling hooks and writing logs.
|
||||||
If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking.
|
If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking.
|
||||||
|
|
||||||
Situation when locking is not needed includes:
|
Situation when locking is not needed includes:
|
||||||
|
@ -508,6 +500,6 @@ Situation when locking is not needed includes:
|
||||||
|
|
||||||
1) logger.Out is protected by locks.
|
1) logger.Out is protected by locks.
|
||||||
|
|
||||||
2) logger.Out is an os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allows multi-thread/multi-process writing)
|
2) logger.Out is a os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allow multi-thread/multi-process writing)
|
||||||
|
|
||||||
(Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/)
|
(Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/)
|
||||||
|
|
18
vendor/github.com/sirupsen/logrus/alt_exit.go
generated
vendored
18
vendor/github.com/sirupsen/logrus/alt_exit.go
generated
vendored
|
@ -51,9 +51,9 @@ func Exit(code int) {
|
||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterExitHandler appends a Logrus Exit handler to the list of handlers,
|
// RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke
|
||||||
// call logrus.Exit to invoke all handlers. The handlers will also be invoked when
|
// all handlers. The handlers will also be invoked when any Fatal log entry is
|
||||||
// any Fatal log entry is made.
|
// made.
|
||||||
//
|
//
|
||||||
// This method is useful when a caller wishes to use logrus to log a fatal
|
// This method is useful when a caller wishes to use logrus to log a fatal
|
||||||
// message but also needs to gracefully shutdown. An example usecase could be
|
// message but also needs to gracefully shutdown. An example usecase could be
|
||||||
|
@ -62,15 +62,3 @@ func Exit(code int) {
|
||||||
func RegisterExitHandler(handler func()) {
|
func RegisterExitHandler(handler func()) {
|
||||||
handlers = append(handlers, handler)
|
handlers = append(handlers, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeferExitHandler prepends a Logrus Exit handler to the list of handlers,
|
|
||||||
// call logrus.Exit to invoke all handlers. The handlers will also be invoked when
|
|
||||||
// any Fatal log entry is made.
|
|
||||||
//
|
|
||||||
// This method is useful when a caller wishes to use logrus to log a fatal
|
|
||||||
// message but also needs to gracefully shutdown. An example usecase could be
|
|
||||||
// closing database connections, or sending a alert that the application is
|
|
||||||
// closing.
|
|
||||||
func DeferExitHandler(handler func()) {
|
|
||||||
handlers = append([]func(){handler}, handlers...)
|
|
||||||
}
|
|
||||||
|
|
83
vendor/github.com/sirupsen/logrus/alt_exit_test.go
generated
vendored
Normal file
83
vendor/github.com/sirupsen/logrus/alt_exit_test.go
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
package logrus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRegister(t *testing.T) {
|
||||||
|
current := len(handlers)
|
||||||
|
RegisterExitHandler(func() {})
|
||||||
|
if len(handlers) != current+1 {
|
||||||
|
t.Fatalf("expected %d handlers, got %d", current+1, len(handlers))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHandler(t *testing.T) {
|
||||||
|
tempDir, err := ioutil.TempDir("", "test_handler")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("can't create temp dir. %q", err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tempDir)
|
||||||
|
|
||||||
|
gofile := filepath.Join(tempDir, "gofile.go")
|
||||||
|
if err := ioutil.WriteFile(gofile, testprog, 0666); err != nil {
|
||||||
|
t.Fatalf("can't create go file. %q", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
outfile := filepath.Join(tempDir, "outfile.out")
|
||||||
|
arg := time.Now().UTC().String()
|
||||||
|
err = exec.Command("go", "run", gofile, outfile, arg).Run()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("completed normally, should have failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := ioutil.ReadFile(outfile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't read output file %s. %q", outfile, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(data) != arg {
|
||||||
|
t.Fatalf("bad data. Expected %q, got %q", data, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testprog = []byte(`
|
||||||
|
// Test program for atexit, gets output file and data as arguments and writes
|
||||||
|
// data to output file in atexit handler.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
var outfile = ""
|
||||||
|
var data = ""
|
||||||
|
|
||||||
|
func handler() {
|
||||||
|
ioutil.WriteFile(outfile, []byte(data), 0666)
|
||||||
|
}
|
||||||
|
|
||||||
|
func badHandler() {
|
||||||
|
n := 0
|
||||||
|
fmt.Println(1/n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
outfile = flag.Arg(0)
|
||||||
|
data = flag.Arg(1)
|
||||||
|
|
||||||
|
logrus.RegisterExitHandler(handler)
|
||||||
|
logrus.RegisterExitHandler(badHandler)
|
||||||
|
logrus.Fatal("Bye bye")
|
||||||
|
}
|
||||||
|
`)
|
52
vendor/github.com/sirupsen/logrus/buffer_pool.go
generated
vendored
52
vendor/github.com/sirupsen/logrus/buffer_pool.go
generated
vendored
|
@ -1,52 +0,0 @@
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
bufferPool BufferPool
|
|
||||||
)
|
|
||||||
|
|
||||||
type BufferPool interface {
|
|
||||||
Put(*bytes.Buffer)
|
|
||||||
Get() *bytes.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
type defaultPool struct {
|
|
||||||
pool *sync.Pool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *defaultPool) Put(buf *bytes.Buffer) {
|
|
||||||
p.pool.Put(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *defaultPool) Get() *bytes.Buffer {
|
|
||||||
return p.pool.Get().(*bytes.Buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getBuffer() *bytes.Buffer {
|
|
||||||
return bufferPool.Get()
|
|
||||||
}
|
|
||||||
|
|
||||||
func putBuffer(buf *bytes.Buffer) {
|
|
||||||
buf.Reset()
|
|
||||||
bufferPool.Put(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetBufferPool allows to replace the default logrus buffer pool
|
|
||||||
// to better meets the specific needs of an application.
|
|
||||||
func SetBufferPool(bp BufferPool) {
|
|
||||||
bufferPool = bp
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
SetBufferPool(&defaultPool{
|
|
||||||
pool: &sync.Pool{
|
|
||||||
New: func() interface{} {
|
|
||||||
return new(bytes.Buffer)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
334
vendor/github.com/sirupsen/logrus/entry.go
generated
vendored
334
vendor/github.com/sirupsen/logrus/entry.go
generated
vendored
|
@ -2,45 +2,29 @@ package logrus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var bufferPool *sync.Pool
|
||||||
|
|
||||||
// qualified package name, cached at first use
|
|
||||||
logrusPackage string
|
|
||||||
|
|
||||||
// Positions in the call stack when tracing to report the calling method
|
|
||||||
minimumCallerDepth int
|
|
||||||
|
|
||||||
// Used for caller information initialisation
|
|
||||||
callerInitOnce sync.Once
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
maximumCallerDepth int = 25
|
|
||||||
knownLogrusFrames int = 4
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// start at the bottom of the stack before the package-name cache is primed
|
bufferPool = &sync.Pool{
|
||||||
minimumCallerDepth = 1
|
New: func() interface{} {
|
||||||
|
return new(bytes.Buffer)
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defines the key when adding errors using WithError.
|
// Defines the key when adding errors using WithError.
|
||||||
var ErrorKey = "error"
|
var ErrorKey = "error"
|
||||||
|
|
||||||
// An entry is the final or intermediate Logrus logging entry. It contains all
|
// An entry is the final or intermediate Logrus logging entry. It contains all
|
||||||
// the fields passed with WithField{,s}. It's finally logged when Trace, Debug,
|
// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
|
||||||
// Info, Warn, Error, Fatal or Panic is called on it. These objects can be
|
// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
|
||||||
// reused and passed around as much as you wish to avoid field duplication.
|
// passed around as much as you wish to avoid field duplication.
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
Logger *Logger
|
Logger *Logger
|
||||||
|
|
||||||
|
@ -50,43 +34,29 @@ type Entry struct {
|
||||||
// Time at which the log entry was created
|
// Time at which the log entry was created
|
||||||
Time time.Time
|
Time time.Time
|
||||||
|
|
||||||
// Level the log entry was logged at: Trace, Debug, Info, Warn, Error, Fatal or Panic
|
// Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
|
||||||
// This field will be set on entry firing and the value will be equal to the one in Logger struct field.
|
// This field will be set on entry firing and the value will be equal to the one in Logger struct field.
|
||||||
Level Level
|
Level Level
|
||||||
|
|
||||||
// Calling method, with package name
|
// Message passed to Debug, Info, Warn, Error, Fatal or Panic
|
||||||
Caller *runtime.Frame
|
|
||||||
|
|
||||||
// Message passed to Trace, Debug, Info, Warn, Error, Fatal or Panic
|
|
||||||
Message string
|
Message string
|
||||||
|
|
||||||
// When formatter is called in entry.log(), a Buffer may be set to entry
|
// When formatter is called in entry.log(), an Buffer may be set to entry
|
||||||
Buffer *bytes.Buffer
|
Buffer *bytes.Buffer
|
||||||
|
|
||||||
// Contains the context set by the user. Useful for hook processing etc.
|
|
||||||
Context context.Context
|
|
||||||
|
|
||||||
// err may contain a field formatting error
|
|
||||||
err string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEntry(logger *Logger) *Entry {
|
func NewEntry(logger *Logger) *Entry {
|
||||||
return &Entry{
|
return &Entry{
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
// Default is three fields, plus one optional. Give a little extra room.
|
// Default is three fields, give a little extra room
|
||||||
Data: make(Fields, 6),
|
Data: make(Fields, 5),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the bytes representation of this entry from the formatter.
|
|
||||||
func (entry *Entry) Bytes() ([]byte, error) {
|
|
||||||
return entry.Logger.Formatter.Format(entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the string representation from the reader and ultimately the
|
// Returns the string representation from the reader and ultimately the
|
||||||
// formatter.
|
// formatter.
|
||||||
func (entry *Entry) String() (string, error) {
|
func (entry *Entry) String() (string, error) {
|
||||||
serialized, err := entry.Bytes()
|
serialized, err := entry.Logger.Formatter.Format(entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -99,15 +69,6 @@ func (entry *Entry) WithError(err error) *Entry {
|
||||||
return entry.WithField(ErrorKey, err)
|
return entry.WithField(ErrorKey, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a context to the Entry.
|
|
||||||
func (entry *Entry) WithContext(ctx context.Context) *Entry {
|
|
||||||
dataCopy := make(Fields, len(entry.Data))
|
|
||||||
for k, v := range entry.Data {
|
|
||||||
dataCopy[k] = v
|
|
||||||
}
|
|
||||||
return &Entry{Logger: entry.Logger, Data: dataCopy, Time: entry.Time, err: entry.err, Context: ctx}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a single field to the Entry.
|
// Add a single field to the Entry.
|
||||||
func (entry *Entry) WithField(key string, value interface{}) *Entry {
|
func (entry *Entry) WithField(key string, value interface{}) *Entry {
|
||||||
return entry.WithFields(Fields{key: value})
|
return entry.WithFields(Fields{key: value})
|
||||||
|
@ -119,134 +80,43 @@ func (entry *Entry) WithFields(fields Fields) *Entry {
|
||||||
for k, v := range entry.Data {
|
for k, v := range entry.Data {
|
||||||
data[k] = v
|
data[k] = v
|
||||||
}
|
}
|
||||||
fieldErr := entry.err
|
|
||||||
for k, v := range fields {
|
for k, v := range fields {
|
||||||
isErrField := false
|
|
||||||
if t := reflect.TypeOf(v); t != nil {
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Func:
|
|
||||||
isErrField = true
|
|
||||||
case reflect.Ptr:
|
|
||||||
isErrField = t.Elem().Kind() == reflect.Func
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isErrField {
|
|
||||||
tmp := fmt.Sprintf("can not add field %q", k)
|
|
||||||
if fieldErr != "" {
|
|
||||||
fieldErr = entry.err + ", " + tmp
|
|
||||||
} else {
|
|
||||||
fieldErr = tmp
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
data[k] = v
|
data[k] = v
|
||||||
}
|
}
|
||||||
}
|
return &Entry{Logger: entry.Logger, Data: data}
|
||||||
return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr, Context: entry.Context}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overrides the time of the Entry.
|
|
||||||
func (entry *Entry) WithTime(t time.Time) *Entry {
|
|
||||||
dataCopy := make(Fields, len(entry.Data))
|
|
||||||
for k, v := range entry.Data {
|
|
||||||
dataCopy[k] = v
|
|
||||||
}
|
|
||||||
return &Entry{Logger: entry.Logger, Data: dataCopy, Time: t, err: entry.err, Context: entry.Context}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getPackageName reduces a fully qualified function name to the package name
|
|
||||||
// There really ought to be to be a better way...
|
|
||||||
func getPackageName(f string) string {
|
|
||||||
for {
|
|
||||||
lastPeriod := strings.LastIndex(f, ".")
|
|
||||||
lastSlash := strings.LastIndex(f, "/")
|
|
||||||
if lastPeriod > lastSlash {
|
|
||||||
f = f[:lastPeriod]
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
// getCaller retrieves the name of the first non-logrus calling function
|
|
||||||
func getCaller() *runtime.Frame {
|
|
||||||
// cache this package's fully-qualified name
|
|
||||||
callerInitOnce.Do(func() {
|
|
||||||
pcs := make([]uintptr, maximumCallerDepth)
|
|
||||||
_ = runtime.Callers(0, pcs)
|
|
||||||
|
|
||||||
// dynamic get the package name and the minimum caller depth
|
|
||||||
for i := 0; i < maximumCallerDepth; i++ {
|
|
||||||
funcName := runtime.FuncForPC(pcs[i]).Name()
|
|
||||||
if strings.Contains(funcName, "getCaller") {
|
|
||||||
logrusPackage = getPackageName(funcName)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
minimumCallerDepth = knownLogrusFrames
|
|
||||||
})
|
|
||||||
|
|
||||||
// Restrict the lookback frames to avoid runaway lookups
|
|
||||||
pcs := make([]uintptr, maximumCallerDepth)
|
|
||||||
depth := runtime.Callers(minimumCallerDepth, pcs)
|
|
||||||
frames := runtime.CallersFrames(pcs[:depth])
|
|
||||||
|
|
||||||
for f, again := frames.Next(); again; f, again = frames.Next() {
|
|
||||||
pkg := getPackageName(f.Function)
|
|
||||||
|
|
||||||
// If the caller isn't part of this package, we're done
|
|
||||||
if pkg != logrusPackage {
|
|
||||||
return &f //nolint:scopelint
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we got here, we failed to find the caller's context
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry Entry) HasCaller() (has bool) {
|
|
||||||
return entry.Logger != nil &&
|
|
||||||
entry.Logger.ReportCaller &&
|
|
||||||
entry.Caller != nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is not declared with a pointer value because otherwise
|
// This function is not declared with a pointer value because otherwise
|
||||||
// race conditions will occur when using multiple goroutines
|
// race conditions will occur when using multiple goroutines
|
||||||
func (entry Entry) log(level Level, msg string) {
|
func (entry Entry) log(level Level, msg string) {
|
||||||
var buffer *bytes.Buffer
|
var buffer *bytes.Buffer
|
||||||
|
|
||||||
// Default to now, but allow users to override if they want.
|
|
||||||
//
|
|
||||||
// We don't have to worry about polluting future calls to Entry#log()
|
|
||||||
// with this assignment because this function is declared with a
|
|
||||||
// non-pointer receiver.
|
|
||||||
if entry.Time.IsZero() {
|
|
||||||
entry.Time = time.Now()
|
entry.Time = time.Now()
|
||||||
}
|
|
||||||
|
|
||||||
entry.Level = level
|
entry.Level = level
|
||||||
entry.Message = msg
|
entry.Message = msg
|
||||||
|
|
||||||
|
if err := entry.Logger.Hooks.Fire(level, &entry); err != nil {
|
||||||
entry.Logger.mu.Lock()
|
entry.Logger.mu.Lock()
|
||||||
if entry.Logger.ReportCaller {
|
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
|
||||||
entry.Caller = getCaller()
|
entry.Logger.mu.Unlock()
|
||||||
|
}
|
||||||
|
buffer = bufferPool.Get().(*bytes.Buffer)
|
||||||
|
buffer.Reset()
|
||||||
|
defer bufferPool.Put(buffer)
|
||||||
|
entry.Buffer = buffer
|
||||||
|
serialized, err := entry.Logger.Formatter.Format(&entry)
|
||||||
|
entry.Buffer = nil
|
||||||
|
if err != nil {
|
||||||
|
entry.Logger.mu.Lock()
|
||||||
|
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
|
||||||
|
entry.Logger.mu.Unlock()
|
||||||
|
} else {
|
||||||
|
entry.Logger.mu.Lock()
|
||||||
|
_, err = entry.Logger.Out.Write(serialized)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
|
||||||
}
|
}
|
||||||
entry.Logger.mu.Unlock()
|
entry.Logger.mu.Unlock()
|
||||||
|
}
|
||||||
entry.fireHooks()
|
|
||||||
|
|
||||||
buffer = getBuffer()
|
|
||||||
defer func() {
|
|
||||||
entry.Buffer = nil
|
|
||||||
putBuffer(buffer)
|
|
||||||
}()
|
|
||||||
buffer.Reset()
|
|
||||||
entry.Buffer = buffer
|
|
||||||
|
|
||||||
entry.write()
|
|
||||||
|
|
||||||
entry.Buffer = nil
|
|
||||||
|
|
||||||
// To avoid Entry#log() returning a value that only would make sense for
|
// To avoid Entry#log() returning a value that only would make sense for
|
||||||
// panic() to use in Entry#Panic(), we avoid the allocation by checking
|
// panic() to use in Entry#Panic(), we avoid the allocation by checking
|
||||||
|
@ -256,40 +126,10 @@ func (entry Entry) log(level Level, msg string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) fireHooks() {
|
|
||||||
entry.Logger.mu.Lock()
|
|
||||||
defer entry.Logger.mu.Unlock()
|
|
||||||
err := entry.Logger.Hooks.Fire(entry.Level, entry)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) write() {
|
|
||||||
entry.Logger.mu.Lock()
|
|
||||||
defer entry.Logger.mu.Unlock()
|
|
||||||
serialized, err := entry.Logger.Formatter.Format(entry)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, err = entry.Logger.Out.Write(serialized); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Log(level Level, args ...interface{}) {
|
|
||||||
if entry.Logger.IsLevelEnabled(level) {
|
|
||||||
entry.log(level, fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Trace(args ...interface{}) {
|
|
||||||
entry.Log(TraceLevel, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Debug(args ...interface{}) {
|
func (entry *Entry) Debug(args ...interface{}) {
|
||||||
entry.Log(DebugLevel, args...)
|
if entry.Logger.level() >= DebugLevel {
|
||||||
|
entry.log(DebugLevel, fmt.Sprint(args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Print(args ...interface{}) {
|
func (entry *Entry) Print(args ...interface{}) {
|
||||||
|
@ -297,11 +137,15 @@ func (entry *Entry) Print(args ...interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Info(args ...interface{}) {
|
func (entry *Entry) Info(args ...interface{}) {
|
||||||
entry.Log(InfoLevel, args...)
|
if entry.Logger.level() >= InfoLevel {
|
||||||
|
entry.log(InfoLevel, fmt.Sprint(args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Warn(args ...interface{}) {
|
func (entry *Entry) Warn(args ...interface{}) {
|
||||||
entry.Log(WarnLevel, args...)
|
if entry.Logger.level() >= WarnLevel {
|
||||||
|
entry.log(WarnLevel, fmt.Sprint(args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Warning(args ...interface{}) {
|
func (entry *Entry) Warning(args ...interface{}) {
|
||||||
|
@ -309,37 +153,37 @@ func (entry *Entry) Warning(args ...interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Error(args ...interface{}) {
|
func (entry *Entry) Error(args ...interface{}) {
|
||||||
entry.Log(ErrorLevel, args...)
|
if entry.Logger.level() >= ErrorLevel {
|
||||||
|
entry.log(ErrorLevel, fmt.Sprint(args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Fatal(args ...interface{}) {
|
func (entry *Entry) Fatal(args ...interface{}) {
|
||||||
entry.Log(FatalLevel, args...)
|
if entry.Logger.level() >= FatalLevel {
|
||||||
entry.Logger.Exit(1)
|
entry.log(FatalLevel, fmt.Sprint(args...))
|
||||||
|
}
|
||||||
|
Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Panic(args ...interface{}) {
|
func (entry *Entry) Panic(args ...interface{}) {
|
||||||
entry.Log(PanicLevel, args...)
|
if entry.Logger.level() >= PanicLevel {
|
||||||
|
entry.log(PanicLevel, fmt.Sprint(args...))
|
||||||
|
}
|
||||||
panic(fmt.Sprint(args...))
|
panic(fmt.Sprint(args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Entry Printf family functions
|
// Entry Printf family functions
|
||||||
|
|
||||||
func (entry *Entry) Logf(level Level, format string, args ...interface{}) {
|
|
||||||
if entry.Logger.IsLevelEnabled(level) {
|
|
||||||
entry.Log(level, fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Tracef(format string, args ...interface{}) {
|
|
||||||
entry.Logf(TraceLevel, format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Debugf(format string, args ...interface{}) {
|
func (entry *Entry) Debugf(format string, args ...interface{}) {
|
||||||
entry.Logf(DebugLevel, format, args...)
|
if entry.Logger.level() >= DebugLevel {
|
||||||
|
entry.Debug(fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Infof(format string, args ...interface{}) {
|
func (entry *Entry) Infof(format string, args ...interface{}) {
|
||||||
entry.Logf(InfoLevel, format, args...)
|
if entry.Logger.level() >= InfoLevel {
|
||||||
|
entry.Info(fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Printf(format string, args ...interface{}) {
|
func (entry *Entry) Printf(format string, args ...interface{}) {
|
||||||
|
@ -347,7 +191,9 @@ func (entry *Entry) Printf(format string, args ...interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Warnf(format string, args ...interface{}) {
|
func (entry *Entry) Warnf(format string, args ...interface{}) {
|
||||||
entry.Logf(WarnLevel, format, args...)
|
if entry.Logger.level() >= WarnLevel {
|
||||||
|
entry.Warn(fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Warningf(format string, args ...interface{}) {
|
func (entry *Entry) Warningf(format string, args ...interface{}) {
|
||||||
|
@ -355,36 +201,36 @@ func (entry *Entry) Warningf(format string, args ...interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Errorf(format string, args ...interface{}) {
|
func (entry *Entry) Errorf(format string, args ...interface{}) {
|
||||||
entry.Logf(ErrorLevel, format, args...)
|
if entry.Logger.level() >= ErrorLevel {
|
||||||
|
entry.Error(fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Fatalf(format string, args ...interface{}) {
|
func (entry *Entry) Fatalf(format string, args ...interface{}) {
|
||||||
entry.Logf(FatalLevel, format, args...)
|
if entry.Logger.level() >= FatalLevel {
|
||||||
entry.Logger.Exit(1)
|
entry.Fatal(fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
|
Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Panicf(format string, args ...interface{}) {
|
func (entry *Entry) Panicf(format string, args ...interface{}) {
|
||||||
entry.Logf(PanicLevel, format, args...)
|
if entry.Logger.level() >= PanicLevel {
|
||||||
|
entry.Panic(fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Entry Println family functions
|
// Entry Println family functions
|
||||||
|
|
||||||
func (entry *Entry) Logln(level Level, args ...interface{}) {
|
|
||||||
if entry.Logger.IsLevelEnabled(level) {
|
|
||||||
entry.Log(level, entry.sprintlnn(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Traceln(args ...interface{}) {
|
|
||||||
entry.Logln(TraceLevel, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Debugln(args ...interface{}) {
|
func (entry *Entry) Debugln(args ...interface{}) {
|
||||||
entry.Logln(DebugLevel, args...)
|
if entry.Logger.level() >= DebugLevel {
|
||||||
|
entry.Debug(entry.sprintlnn(args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Infoln(args ...interface{}) {
|
func (entry *Entry) Infoln(args ...interface{}) {
|
||||||
entry.Logln(InfoLevel, args...)
|
if entry.Logger.level() >= InfoLevel {
|
||||||
|
entry.Info(entry.sprintlnn(args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Println(args ...interface{}) {
|
func (entry *Entry) Println(args ...interface{}) {
|
||||||
|
@ -392,7 +238,9 @@ func (entry *Entry) Println(args ...interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Warnln(args ...interface{}) {
|
func (entry *Entry) Warnln(args ...interface{}) {
|
||||||
entry.Logln(WarnLevel, args...)
|
if entry.Logger.level() >= WarnLevel {
|
||||||
|
entry.Warn(entry.sprintlnn(args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Warningln(args ...interface{}) {
|
func (entry *Entry) Warningln(args ...interface{}) {
|
||||||
|
@ -400,16 +248,22 @@ func (entry *Entry) Warningln(args ...interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Errorln(args ...interface{}) {
|
func (entry *Entry) Errorln(args ...interface{}) {
|
||||||
entry.Logln(ErrorLevel, args...)
|
if entry.Logger.level() >= ErrorLevel {
|
||||||
|
entry.Error(entry.sprintlnn(args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Fatalln(args ...interface{}) {
|
func (entry *Entry) Fatalln(args ...interface{}) {
|
||||||
entry.Logln(FatalLevel, args...)
|
if entry.Logger.level() >= FatalLevel {
|
||||||
entry.Logger.Exit(1)
|
entry.Fatal(entry.sprintlnn(args...))
|
||||||
|
}
|
||||||
|
Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Panicln(args ...interface{}) {
|
func (entry *Entry) Panicln(args ...interface{}) {
|
||||||
entry.Logln(PanicLevel, args...)
|
if entry.Logger.level() >= PanicLevel {
|
||||||
|
entry.Panic(entry.sprintlnn(args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sprintlnn => Sprint no newline. This is to get the behavior of how
|
// Sprintlnn => Sprint no newline. This is to get the behavior of how
|
||||||
|
|
77
vendor/github.com/sirupsen/logrus/entry_test.go
generated
vendored
Normal file
77
vendor/github.com/sirupsen/logrus/entry_test.go
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
package logrus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEntryWithError(t *testing.T) {
|
||||||
|
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
ErrorKey = "error"
|
||||||
|
}()
|
||||||
|
|
||||||
|
err := fmt.Errorf("kaboom at layer %d", 4711)
|
||||||
|
|
||||||
|
assert.Equal(err, WithError(err).Data["error"])
|
||||||
|
|
||||||
|
logger := New()
|
||||||
|
logger.Out = &bytes.Buffer{}
|
||||||
|
entry := NewEntry(logger)
|
||||||
|
|
||||||
|
assert.Equal(err, entry.WithError(err).Data["error"])
|
||||||
|
|
||||||
|
ErrorKey = "err"
|
||||||
|
|
||||||
|
assert.Equal(err, entry.WithError(err).Data["err"])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEntryPanicln(t *testing.T) {
|
||||||
|
errBoom := fmt.Errorf("boom time")
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
p := recover()
|
||||||
|
assert.NotNil(t, p)
|
||||||
|
|
||||||
|
switch pVal := p.(type) {
|
||||||
|
case *Entry:
|
||||||
|
assert.Equal(t, "kaboom", pVal.Message)
|
||||||
|
assert.Equal(t, errBoom, pVal.Data["err"])
|
||||||
|
default:
|
||||||
|
t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
logger := New()
|
||||||
|
logger.Out = &bytes.Buffer{}
|
||||||
|
entry := NewEntry(logger)
|
||||||
|
entry.WithField("err", errBoom).Panicln("kaboom")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEntryPanicf(t *testing.T) {
|
||||||
|
errBoom := fmt.Errorf("boom again")
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
p := recover()
|
||||||
|
assert.NotNil(t, p)
|
||||||
|
|
||||||
|
switch pVal := p.(type) {
|
||||||
|
case *Entry:
|
||||||
|
assert.Equal(t, "kaboom true", pVal.Message)
|
||||||
|
assert.Equal(t, errBoom, pVal.Data["err"])
|
||||||
|
default:
|
||||||
|
t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
logger := New()
|
||||||
|
logger.Out = &bytes.Buffer{}
|
||||||
|
entry := NewEntry(logger)
|
||||||
|
entry.WithField("err", errBoom).Panicf("kaboom %v", true)
|
||||||
|
}
|
69
vendor/github.com/sirupsen/logrus/example_basic_test.go
generated
vendored
Normal file
69
vendor/github.com/sirupsen/logrus/example_basic_test.go
generated
vendored
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
package logrus_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Example_basic() {
|
||||||
|
var log = logrus.New()
|
||||||
|
log.Formatter = new(logrus.JSONFormatter)
|
||||||
|
log.Formatter = new(logrus.TextFormatter) //default
|
||||||
|
log.Formatter.(*logrus.TextFormatter).DisableTimestamp = true // remove timestamp from test output
|
||||||
|
log.Level = logrus.DebugLevel
|
||||||
|
log.Out = os.Stdout
|
||||||
|
|
||||||
|
// file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666)
|
||||||
|
// if err == nil {
|
||||||
|
// log.Out = file
|
||||||
|
// } else {
|
||||||
|
// log.Info("Failed to log to file, using default stderr")
|
||||||
|
// }
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
err := recover()
|
||||||
|
if err != nil {
|
||||||
|
entry := err.(*logrus.Entry)
|
||||||
|
log.WithFields(logrus.Fields{
|
||||||
|
"omg": true,
|
||||||
|
"err_animal": entry.Data["animal"],
|
||||||
|
"err_size": entry.Data["size"],
|
||||||
|
"err_level": entry.Level,
|
||||||
|
"err_message": entry.Message,
|
||||||
|
"number": 100,
|
||||||
|
}).Error("The ice breaks!") // or use Fatal() to force the process to exit with a nonzero code
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
log.WithFields(logrus.Fields{
|
||||||
|
"animal": "walrus",
|
||||||
|
"number": 8,
|
||||||
|
}).Debug("Started observing beach")
|
||||||
|
|
||||||
|
log.WithFields(logrus.Fields{
|
||||||
|
"animal": "walrus",
|
||||||
|
"size": 10,
|
||||||
|
}).Info("A group of walrus emerges from the ocean")
|
||||||
|
|
||||||
|
log.WithFields(logrus.Fields{
|
||||||
|
"omg": true,
|
||||||
|
"number": 122,
|
||||||
|
}).Warn("The group's number increased tremendously!")
|
||||||
|
|
||||||
|
log.WithFields(logrus.Fields{
|
||||||
|
"temperature": -4,
|
||||||
|
}).Debug("Temperature changes")
|
||||||
|
|
||||||
|
log.WithFields(logrus.Fields{
|
||||||
|
"animal": "orca",
|
||||||
|
"size": 9009,
|
||||||
|
}).Panic("It's over 9000!")
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// level=debug msg="Started observing beach" animal=walrus number=8
|
||||||
|
// level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10
|
||||||
|
// level=warning msg="The group's number increased tremendously!" number=122 omg=true
|
||||||
|
// level=debug msg="Temperature changes" temperature=-4
|
||||||
|
// level=panic msg="It's over 9000!" animal=orca size=9009
|
||||||
|
// level=error msg="The ice breaks!" err_animal=orca err_level=panic err_message="It's over 9000!" err_size=9009 number=100 omg=true
|
||||||
|
}
|
35
vendor/github.com/sirupsen/logrus/example_hook_test.go
generated
vendored
Normal file
35
vendor/github.com/sirupsen/logrus/example_hook_test.go
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package logrus_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"gopkg.in/gemnasium/logrus-airbrake-hook.v2"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Example_hook() {
|
||||||
|
var log = logrus.New()
|
||||||
|
log.Formatter = new(logrus.TextFormatter) // default
|
||||||
|
log.Formatter.(*logrus.TextFormatter).DisableTimestamp = true // remove timestamp from test output
|
||||||
|
log.Hooks.Add(airbrake.NewHook(123, "xyz", "development"))
|
||||||
|
log.Out = os.Stdout
|
||||||
|
|
||||||
|
log.WithFields(logrus.Fields{
|
||||||
|
"animal": "walrus",
|
||||||
|
"size": 10,
|
||||||
|
}).Info("A group of walrus emerges from the ocean")
|
||||||
|
|
||||||
|
log.WithFields(logrus.Fields{
|
||||||
|
"omg": true,
|
||||||
|
"number": 122,
|
||||||
|
}).Warn("The group's number increased tremendously!")
|
||||||
|
|
||||||
|
log.WithFields(logrus.Fields{
|
||||||
|
"omg": true,
|
||||||
|
"number": 100,
|
||||||
|
}).Error("The ice breaks!")
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10
|
||||||
|
// level=warning msg="The group's number increased tremendously!" number=122 omg=true
|
||||||
|
// level=error msg="The ice breaks!" number=100 omg=true
|
||||||
|
}
|
111
vendor/github.com/sirupsen/logrus/exported.go
generated
vendored
111
vendor/github.com/sirupsen/logrus/exported.go
generated
vendored
|
@ -1,9 +1,7 @@
|
||||||
package logrus
|
package logrus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"io"
|
"io"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -17,38 +15,37 @@ func StandardLogger() *Logger {
|
||||||
|
|
||||||
// SetOutput sets the standard logger output.
|
// SetOutput sets the standard logger output.
|
||||||
func SetOutput(out io.Writer) {
|
func SetOutput(out io.Writer) {
|
||||||
std.SetOutput(out)
|
std.mu.Lock()
|
||||||
|
defer std.mu.Unlock()
|
||||||
|
std.Out = out
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFormatter sets the standard logger formatter.
|
// SetFormatter sets the standard logger formatter.
|
||||||
func SetFormatter(formatter Formatter) {
|
func SetFormatter(formatter Formatter) {
|
||||||
std.SetFormatter(formatter)
|
std.mu.Lock()
|
||||||
}
|
defer std.mu.Unlock()
|
||||||
|
std.Formatter = formatter
|
||||||
// SetReportCaller sets whether the standard logger will include the calling
|
|
||||||
// method as a field.
|
|
||||||
func SetReportCaller(include bool) {
|
|
||||||
std.SetReportCaller(include)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLevel sets the standard logger level.
|
// SetLevel sets the standard logger level.
|
||||||
func SetLevel(level Level) {
|
func SetLevel(level Level) {
|
||||||
|
std.mu.Lock()
|
||||||
|
defer std.mu.Unlock()
|
||||||
std.SetLevel(level)
|
std.SetLevel(level)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLevel returns the standard logger level.
|
// GetLevel returns the standard logger level.
|
||||||
func GetLevel() Level {
|
func GetLevel() Level {
|
||||||
return std.GetLevel()
|
std.mu.Lock()
|
||||||
}
|
defer std.mu.Unlock()
|
||||||
|
return std.level()
|
||||||
// IsLevelEnabled checks if the log level of the standard logger is greater than the level param
|
|
||||||
func IsLevelEnabled(level Level) bool {
|
|
||||||
return std.IsLevelEnabled(level)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddHook adds a hook to the standard logger hooks.
|
// AddHook adds a hook to the standard logger hooks.
|
||||||
func AddHook(hook Hook) {
|
func AddHook(hook Hook) {
|
||||||
std.AddHook(hook)
|
std.mu.Lock()
|
||||||
|
defer std.mu.Unlock()
|
||||||
|
std.Hooks.Add(hook)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key.
|
// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key.
|
||||||
|
@ -56,11 +53,6 @@ func WithError(err error) *Entry {
|
||||||
return std.WithField(ErrorKey, err)
|
return std.WithField(ErrorKey, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithContext creates an entry from the standard logger and adds a context to it.
|
|
||||||
func WithContext(ctx context.Context) *Entry {
|
|
||||||
return std.WithContext(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithField creates an entry from the standard logger and adds a field to
|
// WithField creates an entry from the standard logger and adds a field to
|
||||||
// it. If you want multiple fields, use `WithFields`.
|
// it. If you want multiple fields, use `WithFields`.
|
||||||
//
|
//
|
||||||
|
@ -80,20 +72,6 @@ func WithFields(fields Fields) *Entry {
|
||||||
return std.WithFields(fields)
|
return std.WithFields(fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithTime creates an entry from the standard logger and overrides the time of
|
|
||||||
// logs generated with it.
|
|
||||||
//
|
|
||||||
// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
|
|
||||||
// or Panic on the Entry it returns.
|
|
||||||
func WithTime(t time.Time) *Entry {
|
|
||||||
return std.WithTime(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trace logs a message at level Trace on the standard logger.
|
|
||||||
func Trace(args ...interface{}) {
|
|
||||||
std.Trace(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debug logs a message at level Debug on the standard logger.
|
// Debug logs a message at level Debug on the standard logger.
|
||||||
func Debug(args ...interface{}) {
|
func Debug(args ...interface{}) {
|
||||||
std.Debug(args...)
|
std.Debug(args...)
|
||||||
|
@ -129,61 +107,11 @@ func Panic(args ...interface{}) {
|
||||||
std.Panic(args...)
|
std.Panic(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fatal logs a message at level Fatal on the standard logger then the process will exit with status set to 1.
|
// Fatal logs a message at level Fatal on the standard logger.
|
||||||
func Fatal(args ...interface{}) {
|
func Fatal(args ...interface{}) {
|
||||||
std.Fatal(args...)
|
std.Fatal(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TraceFn logs a message from a func at level Trace on the standard logger.
|
|
||||||
func TraceFn(fn LogFunction) {
|
|
||||||
std.TraceFn(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DebugFn logs a message from a func at level Debug on the standard logger.
|
|
||||||
func DebugFn(fn LogFunction) {
|
|
||||||
std.DebugFn(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrintFn logs a message from a func at level Info on the standard logger.
|
|
||||||
func PrintFn(fn LogFunction) {
|
|
||||||
std.PrintFn(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InfoFn logs a message from a func at level Info on the standard logger.
|
|
||||||
func InfoFn(fn LogFunction) {
|
|
||||||
std.InfoFn(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WarnFn logs a message from a func at level Warn on the standard logger.
|
|
||||||
func WarnFn(fn LogFunction) {
|
|
||||||
std.WarnFn(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WarningFn logs a message from a func at level Warn on the standard logger.
|
|
||||||
func WarningFn(fn LogFunction) {
|
|
||||||
std.WarningFn(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorFn logs a message from a func at level Error on the standard logger.
|
|
||||||
func ErrorFn(fn LogFunction) {
|
|
||||||
std.ErrorFn(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PanicFn logs a message from a func at level Panic on the standard logger.
|
|
||||||
func PanicFn(fn LogFunction) {
|
|
||||||
std.PanicFn(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FatalFn logs a message from a func at level Fatal on the standard logger then the process will exit with status set to 1.
|
|
||||||
func FatalFn(fn LogFunction) {
|
|
||||||
std.FatalFn(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tracef logs a message at level Trace on the standard logger.
|
|
||||||
func Tracef(format string, args ...interface{}) {
|
|
||||||
std.Tracef(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debugf logs a message at level Debug on the standard logger.
|
// Debugf logs a message at level Debug on the standard logger.
|
||||||
func Debugf(format string, args ...interface{}) {
|
func Debugf(format string, args ...interface{}) {
|
||||||
std.Debugf(format, args...)
|
std.Debugf(format, args...)
|
||||||
|
@ -219,16 +147,11 @@ func Panicf(format string, args ...interface{}) {
|
||||||
std.Panicf(format, args...)
|
std.Panicf(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fatalf logs a message at level Fatal on the standard logger then the process will exit with status set to 1.
|
// Fatalf logs a message at level Fatal on the standard logger.
|
||||||
func Fatalf(format string, args ...interface{}) {
|
func Fatalf(format string, args ...interface{}) {
|
||||||
std.Fatalf(format, args...)
|
std.Fatalf(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Traceln logs a message at level Trace on the standard logger.
|
|
||||||
func Traceln(args ...interface{}) {
|
|
||||||
std.Traceln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debugln logs a message at level Debug on the standard logger.
|
// Debugln logs a message at level Debug on the standard logger.
|
||||||
func Debugln(args ...interface{}) {
|
func Debugln(args ...interface{}) {
|
||||||
std.Debugln(args...)
|
std.Debugln(args...)
|
||||||
|
@ -264,7 +187,7 @@ func Panicln(args ...interface{}) {
|
||||||
std.Panicln(args...)
|
std.Panicln(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fatalln logs a message at level Fatal on the standard logger then the process will exit with status set to 1.
|
// Fatalln logs a message at level Fatal on the standard logger.
|
||||||
func Fatalln(args ...interface{}) {
|
func Fatalln(args ...interface{}) {
|
||||||
std.Fatalln(args...)
|
std.Fatalln(args...)
|
||||||
}
|
}
|
||||||
|
|
51
vendor/github.com/sirupsen/logrus/formatter.go
generated
vendored
51
vendor/github.com/sirupsen/logrus/formatter.go
generated
vendored
|
@ -2,16 +2,7 @@ package logrus
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
// Default key names for the default fields
|
const defaultTimestampFormat = time.RFC3339
|
||||||
const (
|
|
||||||
defaultTimestampFormat = time.RFC3339
|
|
||||||
FieldKeyMsg = "msg"
|
|
||||||
FieldKeyLevel = "level"
|
|
||||||
FieldKeyTime = "time"
|
|
||||||
FieldKeyLogrusError = "logrus_error"
|
|
||||||
FieldKeyFunc = "func"
|
|
||||||
FieldKeyFile = "file"
|
|
||||||
)
|
|
||||||
|
|
||||||
// The Formatter interface is used to implement a custom Formatter. It takes an
|
// The Formatter interface is used to implement a custom Formatter. It takes an
|
||||||
// `Entry`. It exposes all the fields, including the default ones:
|
// `Entry`. It exposes all the fields, including the default ones:
|
||||||
|
@ -27,7 +18,7 @@ type Formatter interface {
|
||||||
Format(*Entry) ([]byte, error)
|
Format(*Entry) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is to not silently overwrite `time`, `msg`, `func` and `level` fields when
|
// This is to not silently overwrite `time`, `msg` and `level` fields when
|
||||||
// dumping it. If this code wasn't there doing:
|
// dumping it. If this code wasn't there doing:
|
||||||
//
|
//
|
||||||
// logrus.WithField("level", 1).Info("hello")
|
// logrus.WithField("level", 1).Info("hello")
|
||||||
|
@ -39,40 +30,16 @@ type Formatter interface {
|
||||||
//
|
//
|
||||||
// It's not exported because it's still using Data in an opinionated way. It's to
|
// It's not exported because it's still using Data in an opinionated way. It's to
|
||||||
// avoid code duplication between the two default formatters.
|
// avoid code duplication between the two default formatters.
|
||||||
func prefixFieldClashes(data Fields, fieldMap FieldMap, reportCaller bool) {
|
func prefixFieldClashes(data Fields) {
|
||||||
timeKey := fieldMap.resolve(FieldKeyTime)
|
if t, ok := data["time"]; ok {
|
||||||
if t, ok := data[timeKey]; ok {
|
data["fields.time"] = t
|
||||||
data["fields."+timeKey] = t
|
|
||||||
delete(data, timeKey)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
msgKey := fieldMap.resolve(FieldKeyMsg)
|
if m, ok := data["msg"]; ok {
|
||||||
if m, ok := data[msgKey]; ok {
|
data["fields.msg"] = m
|
||||||
data["fields."+msgKey] = m
|
|
||||||
delete(data, msgKey)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
levelKey := fieldMap.resolve(FieldKeyLevel)
|
if l, ok := data["level"]; ok {
|
||||||
if l, ok := data[levelKey]; ok {
|
data["fields.level"] = l
|
||||||
data["fields."+levelKey] = l
|
|
||||||
delete(data, levelKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
logrusErrKey := fieldMap.resolve(FieldKeyLogrusError)
|
|
||||||
if l, ok := data[logrusErrKey]; ok {
|
|
||||||
data["fields."+logrusErrKey] = l
|
|
||||||
delete(data, logrusErrKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If reportCaller is not set, 'func' will not conflict.
|
|
||||||
if reportCaller {
|
|
||||||
funcKey := fieldMap.resolve(FieldKeyFunc)
|
|
||||||
if l, ok := data[funcKey]; ok {
|
|
||||||
data["fields."+funcKey] = l
|
|
||||||
}
|
|
||||||
fileKey := fieldMap.resolve(FieldKeyFile)
|
|
||||||
if l, ok := data[fileKey]; ok {
|
|
||||||
data["fields."+fileKey] = l
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
101
vendor/github.com/sirupsen/logrus/formatter_bench_test.go
generated
vendored
Normal file
101
vendor/github.com/sirupsen/logrus/formatter_bench_test.go
generated
vendored
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
package logrus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// smallFields is a small size data set for benchmarking
|
||||||
|
var smallFields = Fields{
|
||||||
|
"foo": "bar",
|
||||||
|
"baz": "qux",
|
||||||
|
"one": "two",
|
||||||
|
"three": "four",
|
||||||
|
}
|
||||||
|
|
||||||
|
// largeFields is a large size data set for benchmarking
|
||||||
|
var largeFields = Fields{
|
||||||
|
"foo": "bar",
|
||||||
|
"baz": "qux",
|
||||||
|
"one": "two",
|
||||||
|
"three": "four",
|
||||||
|
"five": "six",
|
||||||
|
"seven": "eight",
|
||||||
|
"nine": "ten",
|
||||||
|
"eleven": "twelve",
|
||||||
|
"thirteen": "fourteen",
|
||||||
|
"fifteen": "sixteen",
|
||||||
|
"seventeen": "eighteen",
|
||||||
|
"nineteen": "twenty",
|
||||||
|
"a": "b",
|
||||||
|
"c": "d",
|
||||||
|
"e": "f",
|
||||||
|
"g": "h",
|
||||||
|
"i": "j",
|
||||||
|
"k": "l",
|
||||||
|
"m": "n",
|
||||||
|
"o": "p",
|
||||||
|
"q": "r",
|
||||||
|
"s": "t",
|
||||||
|
"u": "v",
|
||||||
|
"w": "x",
|
||||||
|
"y": "z",
|
||||||
|
"this": "will",
|
||||||
|
"make": "thirty",
|
||||||
|
"entries": "yeah",
|
||||||
|
}
|
||||||
|
|
||||||
|
var errorFields = Fields{
|
||||||
|
"foo": fmt.Errorf("bar"),
|
||||||
|
"baz": fmt.Errorf("qux"),
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkErrorTextFormatter(b *testing.B) {
|
||||||
|
doBenchmark(b, &TextFormatter{DisableColors: true}, errorFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSmallTextFormatter(b *testing.B) {
|
||||||
|
doBenchmark(b, &TextFormatter{DisableColors: true}, smallFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLargeTextFormatter(b *testing.B) {
|
||||||
|
doBenchmark(b, &TextFormatter{DisableColors: true}, largeFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSmallColoredTextFormatter(b *testing.B) {
|
||||||
|
doBenchmark(b, &TextFormatter{ForceColors: true}, smallFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLargeColoredTextFormatter(b *testing.B) {
|
||||||
|
doBenchmark(b, &TextFormatter{ForceColors: true}, largeFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSmallJSONFormatter(b *testing.B) {
|
||||||
|
doBenchmark(b, &JSONFormatter{}, smallFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLargeJSONFormatter(b *testing.B) {
|
||||||
|
doBenchmark(b, &JSONFormatter{}, largeFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
func doBenchmark(b *testing.B, formatter Formatter, fields Fields) {
|
||||||
|
logger := New()
|
||||||
|
|
||||||
|
entry := &Entry{
|
||||||
|
Time: time.Time{},
|
||||||
|
Level: InfoLevel,
|
||||||
|
Message: "message",
|
||||||
|
Data: fields,
|
||||||
|
Logger: logger,
|
||||||
|
}
|
||||||
|
var d []byte
|
||||||
|
var err error
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
d, err = formatter.Format(entry)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
b.SetBytes(int64(len(d)))
|
||||||
|
}
|
||||||
|
}
|
10
vendor/github.com/sirupsen/logrus/go.mod
generated
vendored
10
vendor/github.com/sirupsen/logrus/go.mod
generated
vendored
|
@ -1,10 +0,0 @@
|
||||||
module github.com/sirupsen/logrus
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
|
||||||
github.com/stretchr/testify v1.2.2
|
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037
|
|
||||||
)
|
|
||||||
|
|
||||||
go 1.13
|
|
10
vendor/github.com/sirupsen/logrus/go.sum
generated
vendored
10
vendor/github.com/sirupsen/logrus/go.sum
generated
vendored
|
@ -1,10 +0,0 @@
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
|
||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
|
|
||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
122
vendor/github.com/sirupsen/logrus/hook_test.go
generated
vendored
Normal file
122
vendor/github.com/sirupsen/logrus/hook_test.go
generated
vendored
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
package logrus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestHook struct {
|
||||||
|
Fired bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hook *TestHook) Fire(entry *Entry) error {
|
||||||
|
hook.Fired = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hook *TestHook) Levels() []Level {
|
||||||
|
return []Level{
|
||||||
|
DebugLevel,
|
||||||
|
InfoLevel,
|
||||||
|
WarnLevel,
|
||||||
|
ErrorLevel,
|
||||||
|
FatalLevel,
|
||||||
|
PanicLevel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHookFires(t *testing.T) {
|
||||||
|
hook := new(TestHook)
|
||||||
|
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.Hooks.Add(hook)
|
||||||
|
assert.Equal(t, hook.Fired, false)
|
||||||
|
|
||||||
|
log.Print("test")
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, hook.Fired, true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type ModifyHook struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hook *ModifyHook) Fire(entry *Entry) error {
|
||||||
|
entry.Data["wow"] = "whale"
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hook *ModifyHook) Levels() []Level {
|
||||||
|
return []Level{
|
||||||
|
DebugLevel,
|
||||||
|
InfoLevel,
|
||||||
|
WarnLevel,
|
||||||
|
ErrorLevel,
|
||||||
|
FatalLevel,
|
||||||
|
PanicLevel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHookCanModifyEntry(t *testing.T) {
|
||||||
|
hook := new(ModifyHook)
|
||||||
|
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.Hooks.Add(hook)
|
||||||
|
log.WithField("wow", "elephant").Print("test")
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["wow"], "whale")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCanFireMultipleHooks(t *testing.T) {
|
||||||
|
hook1 := new(ModifyHook)
|
||||||
|
hook2 := new(TestHook)
|
||||||
|
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.Hooks.Add(hook1)
|
||||||
|
log.Hooks.Add(hook2)
|
||||||
|
|
||||||
|
log.WithField("wow", "elephant").Print("test")
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["wow"], "whale")
|
||||||
|
assert.Equal(t, hook2.Fired, true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type ErrorHook struct {
|
||||||
|
Fired bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hook *ErrorHook) Fire(entry *Entry) error {
|
||||||
|
hook.Fired = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hook *ErrorHook) Levels() []Level {
|
||||||
|
return []Level{
|
||||||
|
ErrorLevel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrorHookShouldntFireOnInfo(t *testing.T) {
|
||||||
|
hook := new(ErrorHook)
|
||||||
|
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.Hooks.Add(hook)
|
||||||
|
log.Info("test")
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, hook.Fired, false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrorHookShouldFireOnError(t *testing.T) {
|
||||||
|
hook := new(ErrorHook)
|
||||||
|
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.Hooks.Add(hook)
|
||||||
|
log.Error("test")
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, hook.Fired, true)
|
||||||
|
})
|
||||||
|
}
|
39
vendor/github.com/sirupsen/logrus/hooks/syslog/README.md
generated
vendored
Normal file
39
vendor/github.com/sirupsen/logrus/hooks/syslog/README.md
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# Syslog Hooks for Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/>
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"log/syslog"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
lSyslog "github.com/sirupsen/logrus/hooks/syslog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
log := logrus.New()
|
||||||
|
hook, err := lSyslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
log.Hooks.Add(hook)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to connect to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). Just assign empty string to the first two parameters of `NewSyslogHook`. It should look like the following.
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"log/syslog"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
lSyslog "github.com/sirupsen/logrus/hooks/syslog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
log := logrus.New()
|
||||||
|
hook, err := lSyslog.NewSyslogHook("", "", syslog.LOG_INFO, "")
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
log.Hooks.Add(hook)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
55
vendor/github.com/sirupsen/logrus/hooks/syslog/syslog.go
generated
vendored
Normal file
55
vendor/github.com/sirupsen/logrus/hooks/syslog/syslog.go
generated
vendored
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
// +build !windows,!nacl,!plan9
|
||||||
|
|
||||||
|
package syslog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log/syslog"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SyslogHook to send logs via syslog.
|
||||||
|
type SyslogHook struct {
|
||||||
|
Writer *syslog.Writer
|
||||||
|
SyslogNetwork string
|
||||||
|
SyslogRaddr string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a hook to be added to an instance of logger. This is called with
|
||||||
|
// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")`
|
||||||
|
// `if err == nil { log.Hooks.Add(hook) }`
|
||||||
|
func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) {
|
||||||
|
w, err := syslog.Dial(network, raddr, priority, tag)
|
||||||
|
return &SyslogHook{w, network, raddr}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
|
||||||
|
line, err := entry.String()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch entry.Level {
|
||||||
|
case logrus.PanicLevel:
|
||||||
|
return hook.Writer.Crit(line)
|
||||||
|
case logrus.FatalLevel:
|
||||||
|
return hook.Writer.Crit(line)
|
||||||
|
case logrus.ErrorLevel:
|
||||||
|
return hook.Writer.Err(line)
|
||||||
|
case logrus.WarnLevel:
|
||||||
|
return hook.Writer.Warning(line)
|
||||||
|
case logrus.InfoLevel:
|
||||||
|
return hook.Writer.Info(line)
|
||||||
|
case logrus.DebugLevel:
|
||||||
|
return hook.Writer.Debug(line)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hook *SyslogHook) Levels() []logrus.Level {
|
||||||
|
return logrus.AllLevels
|
||||||
|
}
|
27
vendor/github.com/sirupsen/logrus/hooks/syslog/syslog_test.go
generated
vendored
Normal file
27
vendor/github.com/sirupsen/logrus/hooks/syslog/syslog_test.go
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package syslog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log/syslog"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalhostAddAndPrint(t *testing.T) {
|
||||||
|
log := logrus.New()
|
||||||
|
hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unable to connect to local syslog.")
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Hooks.Add(hook)
|
||||||
|
|
||||||
|
for _, level := range hook.Levels() {
|
||||||
|
if len(log.Hooks[level]) != 1 {
|
||||||
|
t.Errorf("SyslogHook was not added. The length of log.Hooks[%v]: %v", level, len(log.Hooks[level]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Congratulations!")
|
||||||
|
}
|
95
vendor/github.com/sirupsen/logrus/hooks/test/test.go
generated
vendored
Normal file
95
vendor/github.com/sirupsen/logrus/hooks/test/test.go
generated
vendored
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
// The Test package is used for testing logrus. It is here for backwards
|
||||||
|
// compatibility from when logrus' organization was upper-case. Please use
|
||||||
|
// lower-case logrus and the `null` package instead of this one.
|
||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Hook is a hook designed for dealing with logs in test scenarios.
|
||||||
|
type Hook struct {
|
||||||
|
// Entries is an array of all entries that have been received by this hook.
|
||||||
|
// For safe access, use the AllEntries() method, rather than reading this
|
||||||
|
// value directly.
|
||||||
|
Entries []*logrus.Entry
|
||||||
|
mu sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGlobal installs a test hook for the global logger.
|
||||||
|
func NewGlobal() *Hook {
|
||||||
|
|
||||||
|
hook := new(Hook)
|
||||||
|
logrus.AddHook(hook)
|
||||||
|
|
||||||
|
return hook
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLocal installs a test hook for a given local logger.
|
||||||
|
func NewLocal(logger *logrus.Logger) *Hook {
|
||||||
|
|
||||||
|
hook := new(Hook)
|
||||||
|
logger.Hooks.Add(hook)
|
||||||
|
|
||||||
|
return hook
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNullLogger creates a discarding logger and installs the test hook.
|
||||||
|
func NewNullLogger() (*logrus.Logger, *Hook) {
|
||||||
|
|
||||||
|
logger := logrus.New()
|
||||||
|
logger.Out = ioutil.Discard
|
||||||
|
|
||||||
|
return logger, NewLocal(logger)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Hook) Fire(e *logrus.Entry) error {
|
||||||
|
t.mu.Lock()
|
||||||
|
defer t.mu.Unlock()
|
||||||
|
t.Entries = append(t.Entries, e)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Hook) Levels() []logrus.Level {
|
||||||
|
return logrus.AllLevels
|
||||||
|
}
|
||||||
|
|
||||||
|
// LastEntry returns the last entry that was logged or nil.
|
||||||
|
func (t *Hook) LastEntry() *logrus.Entry {
|
||||||
|
t.mu.RLock()
|
||||||
|
defer t.mu.RUnlock()
|
||||||
|
i := len(t.Entries) - 1
|
||||||
|
if i < 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Make a copy, for safety
|
||||||
|
e := *t.Entries[i]
|
||||||
|
return &e
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllEntries returns all entries that were logged.
|
||||||
|
func (t *Hook) AllEntries() []*logrus.Entry {
|
||||||
|
t.mu.RLock()
|
||||||
|
defer t.mu.RUnlock()
|
||||||
|
// Make a copy so the returned value won't race with future log requests
|
||||||
|
entries := make([]*logrus.Entry, len(t.Entries))
|
||||||
|
for i, entry := range t.Entries {
|
||||||
|
// Make a copy, for safety
|
||||||
|
e := *entry
|
||||||
|
entries[i] = &e
|
||||||
|
}
|
||||||
|
return entries
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset removes all Entries from this test hook.
|
||||||
|
func (t *Hook) Reset() {
|
||||||
|
t.mu.Lock()
|
||||||
|
defer t.mu.Unlock()
|
||||||
|
t.Entries = make([]*logrus.Entry, 0)
|
||||||
|
}
|
39
vendor/github.com/sirupsen/logrus/hooks/test/test_test.go
generated
vendored
Normal file
39
vendor/github.com/sirupsen/logrus/hooks/test/test_test.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAllHooks(t *testing.T) {
|
||||||
|
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
logger, hook := NewNullLogger()
|
||||||
|
assert.Nil(hook.LastEntry())
|
||||||
|
assert.Equal(0, len(hook.Entries))
|
||||||
|
|
||||||
|
logger.Error("Hello error")
|
||||||
|
assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
|
||||||
|
assert.Equal("Hello error", hook.LastEntry().Message)
|
||||||
|
assert.Equal(1, len(hook.Entries))
|
||||||
|
|
||||||
|
logger.Warn("Hello warning")
|
||||||
|
assert.Equal(logrus.WarnLevel, hook.LastEntry().Level)
|
||||||
|
assert.Equal("Hello warning", hook.LastEntry().Message)
|
||||||
|
assert.Equal(2, len(hook.Entries))
|
||||||
|
|
||||||
|
hook.Reset()
|
||||||
|
assert.Nil(hook.LastEntry())
|
||||||
|
assert.Equal(0, len(hook.Entries))
|
||||||
|
|
||||||
|
hook = NewGlobal()
|
||||||
|
|
||||||
|
logrus.Error("Hello error")
|
||||||
|
assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
|
||||||
|
assert.Equal("Hello error", hook.LastEntry().Message)
|
||||||
|
assert.Equal(1, len(hook.Entries))
|
||||||
|
|
||||||
|
}
|
72
vendor/github.com/sirupsen/logrus/json_formatter.go
generated
vendored
72
vendor/github.com/sirupsen/logrus/json_formatter.go
generated
vendored
|
@ -1,10 +1,8 @@
|
||||||
package logrus
|
package logrus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type fieldKey string
|
type fieldKey string
|
||||||
|
@ -12,6 +10,13 @@ type fieldKey string
|
||||||
// FieldMap allows customization of the key names for default fields.
|
// FieldMap allows customization of the key names for default fields.
|
||||||
type FieldMap map[fieldKey]string
|
type FieldMap map[fieldKey]string
|
||||||
|
|
||||||
|
// Default key names for the default fields
|
||||||
|
const (
|
||||||
|
FieldKeyMsg = "msg"
|
||||||
|
FieldKeyLevel = "level"
|
||||||
|
FieldKeyTime = "time"
|
||||||
|
)
|
||||||
|
|
||||||
func (f FieldMap) resolve(key fieldKey) string {
|
func (f FieldMap) resolve(key fieldKey) string {
|
||||||
if k, ok := f[key]; ok {
|
if k, ok := f[key]; ok {
|
||||||
return k
|
return k
|
||||||
|
@ -28,12 +33,6 @@ type JSONFormatter struct {
|
||||||
// DisableTimestamp allows disabling automatic timestamps in output
|
// DisableTimestamp allows disabling automatic timestamps in output
|
||||||
DisableTimestamp bool
|
DisableTimestamp bool
|
||||||
|
|
||||||
// DisableHTMLEscape allows disabling html escaping in output
|
|
||||||
DisableHTMLEscape bool
|
|
||||||
|
|
||||||
// DataKey allows users to put all the log entry parameters into a nested dictionary at a given key.
|
|
||||||
DataKey string
|
|
||||||
|
|
||||||
// FieldMap allows users to customize the names of keys for default fields.
|
// FieldMap allows users to customize the names of keys for default fields.
|
||||||
// As an example:
|
// As an example:
|
||||||
// formatter := &JSONFormatter{
|
// formatter := &JSONFormatter{
|
||||||
|
@ -41,24 +40,14 @@ type JSONFormatter struct {
|
||||||
// FieldKeyTime: "@timestamp",
|
// FieldKeyTime: "@timestamp",
|
||||||
// FieldKeyLevel: "@level",
|
// FieldKeyLevel: "@level",
|
||||||
// FieldKeyMsg: "@message",
|
// FieldKeyMsg: "@message",
|
||||||
// FieldKeyFunc: "@caller",
|
|
||||||
// },
|
// },
|
||||||
// }
|
// }
|
||||||
FieldMap FieldMap
|
FieldMap FieldMap
|
||||||
|
|
||||||
// CallerPrettyfier can be set by the user to modify the content
|
|
||||||
// of the function and file keys in the json data when ReportCaller is
|
|
||||||
// activated. If any of the returned value is the empty string the
|
|
||||||
// corresponding key will be removed from json fields.
|
|
||||||
CallerPrettyfier func(*runtime.Frame) (function string, file string)
|
|
||||||
|
|
||||||
// PrettyPrint will indent all json logs
|
|
||||||
PrettyPrint bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format renders a single log entry
|
// Format renders a single log entry
|
||||||
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
|
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
|
||||||
data := make(Fields, len(entry.Data)+4)
|
data := make(Fields, len(entry.Data)+3)
|
||||||
for k, v := range entry.Data {
|
for k, v := range entry.Data {
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
case error:
|
case error:
|
||||||
|
@ -69,57 +58,22 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
|
||||||
data[k] = v
|
data[k] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
prefixFieldClashes(data)
|
||||||
if f.DataKey != "" {
|
|
||||||
newData := make(Fields, 4)
|
|
||||||
newData[f.DataKey] = data
|
|
||||||
data = newData
|
|
||||||
}
|
|
||||||
|
|
||||||
prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
|
|
||||||
|
|
||||||
timestampFormat := f.TimestampFormat
|
timestampFormat := f.TimestampFormat
|
||||||
if timestampFormat == "" {
|
if timestampFormat == "" {
|
||||||
timestampFormat = defaultTimestampFormat
|
timestampFormat = defaultTimestampFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
if entry.err != "" {
|
|
||||||
data[f.FieldMap.resolve(FieldKeyLogrusError)] = entry.err
|
|
||||||
}
|
|
||||||
if !f.DisableTimestamp {
|
if !f.DisableTimestamp {
|
||||||
data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat)
|
data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat)
|
||||||
}
|
}
|
||||||
data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
|
data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
|
||||||
data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
|
data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
|
||||||
if entry.HasCaller() {
|
|
||||||
funcVal := entry.Caller.Function
|
|
||||||
fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
|
|
||||||
if f.CallerPrettyfier != nil {
|
|
||||||
funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
|
|
||||||
}
|
|
||||||
if funcVal != "" {
|
|
||||||
data[f.FieldMap.resolve(FieldKeyFunc)] = funcVal
|
|
||||||
}
|
|
||||||
if fileVal != "" {
|
|
||||||
data[f.FieldMap.resolve(FieldKeyFile)] = fileVal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var b *bytes.Buffer
|
serialized, err := json.Marshal(data)
|
||||||
if entry.Buffer != nil {
|
if err != nil {
|
||||||
b = entry.Buffer
|
return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
|
||||||
} else {
|
|
||||||
b = &bytes.Buffer{}
|
|
||||||
}
|
}
|
||||||
|
return append(serialized, '\n'), nil
|
||||||
encoder := json.NewEncoder(b)
|
|
||||||
encoder.SetEscapeHTML(!f.DisableHTMLEscape)
|
|
||||||
if f.PrettyPrint {
|
|
||||||
encoder.SetIndent("", " ")
|
|
||||||
}
|
|
||||||
if err := encoder.Encode(data); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to marshal fields to JSON, %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.Bytes(), nil
|
|
||||||
}
|
}
|
||||||
|
|
199
vendor/github.com/sirupsen/logrus/json_formatter_test.go
generated
vendored
Normal file
199
vendor/github.com/sirupsen/logrus/json_formatter_test.go
generated
vendored
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
package logrus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestErrorNotLost(t *testing.T) {
|
||||||
|
formatter := &JSONFormatter{}
|
||||||
|
|
||||||
|
b, err := formatter.Format(WithField("error", errors.New("wild walrus")))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to format entry: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
entry := make(map[string]interface{})
|
||||||
|
err = json.Unmarshal(b, &entry)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry["error"] != "wild walrus" {
|
||||||
|
t.Fatal("Error field not set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrorNotLostOnFieldNotNamedError(t *testing.T) {
|
||||||
|
formatter := &JSONFormatter{}
|
||||||
|
|
||||||
|
b, err := formatter.Format(WithField("omg", errors.New("wild walrus")))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to format entry: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
entry := make(map[string]interface{})
|
||||||
|
err = json.Unmarshal(b, &entry)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry["omg"] != "wild walrus" {
|
||||||
|
t.Fatal("Error field not set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFieldClashWithTime(t *testing.T) {
|
||||||
|
formatter := &JSONFormatter{}
|
||||||
|
|
||||||
|
b, err := formatter.Format(WithField("time", "right now!"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to format entry: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
entry := make(map[string]interface{})
|
||||||
|
err = json.Unmarshal(b, &entry)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry["fields.time"] != "right now!" {
|
||||||
|
t.Fatal("fields.time not set to original time field")
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry["time"] != "0001-01-01T00:00:00Z" {
|
||||||
|
t.Fatal("time field not set to current time, was: ", entry["time"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFieldClashWithMsg(t *testing.T) {
|
||||||
|
formatter := &JSONFormatter{}
|
||||||
|
|
||||||
|
b, err := formatter.Format(WithField("msg", "something"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to format entry: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
entry := make(map[string]interface{})
|
||||||
|
err = json.Unmarshal(b, &entry)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry["fields.msg"] != "something" {
|
||||||
|
t.Fatal("fields.msg not set to original msg field")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFieldClashWithLevel(t *testing.T) {
|
||||||
|
formatter := &JSONFormatter{}
|
||||||
|
|
||||||
|
b, err := formatter.Format(WithField("level", "something"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to format entry: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
entry := make(map[string]interface{})
|
||||||
|
err = json.Unmarshal(b, &entry)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry["fields.level"] != "something" {
|
||||||
|
t.Fatal("fields.level not set to original level field")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEntryEndsWithNewline(t *testing.T) {
|
||||||
|
formatter := &JSONFormatter{}
|
||||||
|
|
||||||
|
b, err := formatter.Format(WithField("level", "something"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to format entry: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b[len(b)-1] != '\n' {
|
||||||
|
t.Fatal("Expected JSON log entry to end with a newline")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONMessageKey(t *testing.T) {
|
||||||
|
formatter := &JSONFormatter{
|
||||||
|
FieldMap: FieldMap{
|
||||||
|
FieldKeyMsg: "message",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := formatter.Format(&Entry{Message: "oh hai"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to format entry: ", err)
|
||||||
|
}
|
||||||
|
s := string(b)
|
||||||
|
if !(strings.Contains(s, "message") && strings.Contains(s, "oh hai")) {
|
||||||
|
t.Fatal("Expected JSON to format message key")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONLevelKey(t *testing.T) {
|
||||||
|
formatter := &JSONFormatter{
|
||||||
|
FieldMap: FieldMap{
|
||||||
|
FieldKeyLevel: "somelevel",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := formatter.Format(WithField("level", "something"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to format entry: ", err)
|
||||||
|
}
|
||||||
|
s := string(b)
|
||||||
|
if !strings.Contains(s, "somelevel") {
|
||||||
|
t.Fatal("Expected JSON to format level key")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONTimeKey(t *testing.T) {
|
||||||
|
formatter := &JSONFormatter{
|
||||||
|
FieldMap: FieldMap{
|
||||||
|
FieldKeyTime: "timeywimey",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := formatter.Format(WithField("level", "something"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to format entry: ", err)
|
||||||
|
}
|
||||||
|
s := string(b)
|
||||||
|
if !strings.Contains(s, "timeywimey") {
|
||||||
|
t.Fatal("Expected JSON to format time key")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONDisableTimestamp(t *testing.T) {
|
||||||
|
formatter := &JSONFormatter{
|
||||||
|
DisableTimestamp: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := formatter.Format(WithField("level", "something"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to format entry: ", err)
|
||||||
|
}
|
||||||
|
s := string(b)
|
||||||
|
if strings.Contains(s, FieldKeyTime) {
|
||||||
|
t.Error("Did not prevent timestamp", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEnableTimestamp(t *testing.T) {
|
||||||
|
formatter := &JSONFormatter{}
|
||||||
|
|
||||||
|
b, err := formatter.Format(WithField("level", "something"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to format entry: ", err)
|
||||||
|
}
|
||||||
|
s := string(b)
|
||||||
|
if !strings.Contains(s, FieldKeyTime) {
|
||||||
|
t.Error("Timestamp not present", s)
|
||||||
|
}
|
||||||
|
}
|
299
vendor/github.com/sirupsen/logrus/logger.go
generated
vendored
299
vendor/github.com/sirupsen/logrus/logger.go
generated
vendored
|
@ -1,23 +1,16 @@
|
||||||
package logrus
|
package logrus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// LogFunction For big messages, it can be more efficient to pass a function
|
|
||||||
// and only call it if the log level is actually enables rather than
|
|
||||||
// generating the log message and then checking if the level is enabled
|
|
||||||
type LogFunction func()[]interface{}
|
|
||||||
|
|
||||||
type Logger struct {
|
type Logger struct {
|
||||||
// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
|
// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
|
||||||
// file, or leave it default which is `os.Stderr`. You can also set this to
|
// file, or leave it default which is `os.Stderr`. You can also set this to
|
||||||
// something more adventurous, such as logging to Kafka.
|
// something more adventorous, such as logging to Kafka.
|
||||||
Out io.Writer
|
Out io.Writer
|
||||||
// Hooks for the logger instance. These allow firing events based on logging
|
// Hooks for the logger instance. These allow firing events based on logging
|
||||||
// levels and log entries. For example, to send errors to an error tracking
|
// levels and log entries. For example, to send errors to an error tracking
|
||||||
|
@ -30,10 +23,6 @@ type Logger struct {
|
||||||
// own that implements the `Formatter` interface, see the `README` or included
|
// own that implements the `Formatter` interface, see the `README` or included
|
||||||
// formatters for examples.
|
// formatters for examples.
|
||||||
Formatter Formatter
|
Formatter Formatter
|
||||||
|
|
||||||
// Flag for whether to log caller info (off by default)
|
|
||||||
ReportCaller bool
|
|
||||||
|
|
||||||
// The logging level the logger should log at. This is typically (and defaults
|
// The logging level the logger should log at. This is typically (and defaults
|
||||||
// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
|
// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
|
||||||
// logged.
|
// logged.
|
||||||
|
@ -42,12 +31,8 @@ type Logger struct {
|
||||||
mu MutexWrap
|
mu MutexWrap
|
||||||
// Reusable empty entry
|
// Reusable empty entry
|
||||||
entryPool sync.Pool
|
entryPool sync.Pool
|
||||||
// Function to exit the application, defaults to `os.Exit()`
|
|
||||||
ExitFunc exitFunc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type exitFunc func(int)
|
|
||||||
|
|
||||||
type MutexWrap struct {
|
type MutexWrap struct {
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
disabled bool
|
disabled bool
|
||||||
|
@ -73,10 +58,10 @@ func (mw *MutexWrap) Disable() {
|
||||||
// `Out` and `Hooks` directly on the default logger instance. You can also just
|
// `Out` and `Hooks` directly on the default logger instance. You can also just
|
||||||
// instantiate your own:
|
// instantiate your own:
|
||||||
//
|
//
|
||||||
// var log = &logrus.Logger{
|
// var log = &Logger{
|
||||||
// Out: os.Stderr,
|
// Out: os.Stderr,
|
||||||
// Formatter: new(logrus.TextFormatter),
|
// Formatter: new(JSONFormatter),
|
||||||
// Hooks: make(logrus.LevelHooks),
|
// Hooks: make(LevelHooks),
|
||||||
// Level: logrus.DebugLevel,
|
// Level: logrus.DebugLevel,
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
@ -87,8 +72,6 @@ func New() *Logger {
|
||||||
Formatter: new(TextFormatter),
|
Formatter: new(TextFormatter),
|
||||||
Hooks: make(LevelHooks),
|
Hooks: make(LevelHooks),
|
||||||
Level: InfoLevel,
|
Level: InfoLevel,
|
||||||
ExitFunc: os.Exit,
|
|
||||||
ReportCaller: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,13 +84,11 @@ func (logger *Logger) newEntry() *Entry {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) releaseEntry(entry *Entry) {
|
func (logger *Logger) releaseEntry(entry *Entry) {
|
||||||
entry.Data = map[string]interface{}{}
|
|
||||||
logger.entryPool.Put(entry)
|
logger.entryPool.Put(entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithField allocates a new entry and adds a field to it.
|
// Adds a field to the log entry, note that it doesn't log until you call
|
||||||
// Debug, Print, Info, Warn, Error, Fatal or Panic must be then applied to
|
// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
|
||||||
// this new returned entry.
|
|
||||||
// If you want multiple fields, use `WithFields`.
|
// If you want multiple fields, use `WithFields`.
|
||||||
func (logger *Logger) WithField(key string, value interface{}) *Entry {
|
func (logger *Logger) WithField(key string, value interface{}) *Entry {
|
||||||
entry := logger.newEntry()
|
entry := logger.newEntry()
|
||||||
|
@ -131,38 +112,20 @@ func (logger *Logger) WithError(err error) *Entry {
|
||||||
return entry.WithError(err)
|
return entry.WithError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a context to the log entry.
|
func (logger *Logger) Debugf(format string, args ...interface{}) {
|
||||||
func (logger *Logger) WithContext(ctx context.Context) *Entry {
|
if logger.level() >= DebugLevel {
|
||||||
entry := logger.newEntry()
|
entry := logger.newEntry()
|
||||||
defer logger.releaseEntry(entry)
|
entry.Debugf(format, args...)
|
||||||
return entry.WithContext(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overrides the time of the log entry.
|
|
||||||
func (logger *Logger) WithTime(t time.Time) *Entry {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
defer logger.releaseEntry(entry)
|
|
||||||
return entry.WithTime(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Logf(level Level, format string, args ...interface{}) {
|
|
||||||
if logger.IsLevelEnabled(level) {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Logf(level, format, args...)
|
|
||||||
logger.releaseEntry(entry)
|
logger.releaseEntry(entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Tracef(format string, args ...interface{}) {
|
|
||||||
logger.Logf(TraceLevel, format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Debugf(format string, args ...interface{}) {
|
|
||||||
logger.Logf(DebugLevel, format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Infof(format string, args ...interface{}) {
|
func (logger *Logger) Infof(format string, args ...interface{}) {
|
||||||
logger.Logf(InfoLevel, format, args...)
|
if logger.level() >= InfoLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Infof(format, args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Printf(format string, args ...interface{}) {
|
func (logger *Logger) Printf(format string, args ...interface{}) {
|
||||||
|
@ -172,138 +135,123 @@ func (logger *Logger) Printf(format string, args ...interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Warnf(format string, args ...interface{}) {
|
func (logger *Logger) Warnf(format string, args ...interface{}) {
|
||||||
logger.Logf(WarnLevel, format, args...)
|
if logger.level() >= WarnLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Warnf(format, args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Warningf(format string, args ...interface{}) {
|
func (logger *Logger) Warningf(format string, args ...interface{}) {
|
||||||
logger.Warnf(format, args...)
|
if logger.level() >= WarnLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Warnf(format, args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Errorf(format string, args ...interface{}) {
|
func (logger *Logger) Errorf(format string, args ...interface{}) {
|
||||||
logger.Logf(ErrorLevel, format, args...)
|
if logger.level() >= ErrorLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Errorf(format, args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Fatalf(format string, args ...interface{}) {
|
func (logger *Logger) Fatalf(format string, args ...interface{}) {
|
||||||
logger.Logf(FatalLevel, format, args...)
|
if logger.level() >= FatalLevel {
|
||||||
logger.Exit(1)
|
entry := logger.newEntry()
|
||||||
|
entry.Fatalf(format, args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
|
Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Panicf(format string, args ...interface{}) {
|
func (logger *Logger) Panicf(format string, args ...interface{}) {
|
||||||
logger.Logf(PanicLevel, format, args...)
|
if logger.level() >= PanicLevel {
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Log(level Level, args ...interface{}) {
|
|
||||||
if logger.IsLevelEnabled(level) {
|
|
||||||
entry := logger.newEntry()
|
entry := logger.newEntry()
|
||||||
entry.Log(level, args...)
|
entry.Panicf(format, args...)
|
||||||
logger.releaseEntry(entry)
|
logger.releaseEntry(entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) LogFn(level Level, fn LogFunction) {
|
|
||||||
if logger.IsLevelEnabled(level) {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Log(level, fn()...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Trace(args ...interface{}) {
|
|
||||||
logger.Log(TraceLevel, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Debug(args ...interface{}) {
|
func (logger *Logger) Debug(args ...interface{}) {
|
||||||
logger.Log(DebugLevel, args...)
|
if logger.level() >= DebugLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Debug(args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Info(args ...interface{}) {
|
func (logger *Logger) Info(args ...interface{}) {
|
||||||
logger.Log(InfoLevel, args...)
|
if logger.level() >= InfoLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Info(args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Print(args ...interface{}) {
|
func (logger *Logger) Print(args ...interface{}) {
|
||||||
entry := logger.newEntry()
|
entry := logger.newEntry()
|
||||||
entry.Print(args...)
|
entry.Info(args...)
|
||||||
logger.releaseEntry(entry)
|
logger.releaseEntry(entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Warn(args ...interface{}) {
|
func (logger *Logger) Warn(args ...interface{}) {
|
||||||
logger.Log(WarnLevel, args...)
|
if logger.level() >= WarnLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Warn(args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Warning(args ...interface{}) {
|
func (logger *Logger) Warning(args ...interface{}) {
|
||||||
logger.Warn(args...)
|
if logger.level() >= WarnLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Warn(args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Error(args ...interface{}) {
|
func (logger *Logger) Error(args ...interface{}) {
|
||||||
logger.Log(ErrorLevel, args...)
|
if logger.level() >= ErrorLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Error(args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Fatal(args ...interface{}) {
|
func (logger *Logger) Fatal(args ...interface{}) {
|
||||||
logger.Log(FatalLevel, args...)
|
if logger.level() >= FatalLevel {
|
||||||
logger.Exit(1)
|
entry := logger.newEntry()
|
||||||
|
entry.Fatal(args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
|
Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Panic(args ...interface{}) {
|
func (logger *Logger) Panic(args ...interface{}) {
|
||||||
logger.Log(PanicLevel, args...)
|
if logger.level() >= PanicLevel {
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) TraceFn(fn LogFunction) {
|
|
||||||
logger.LogFn(TraceLevel, fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) DebugFn(fn LogFunction) {
|
|
||||||
logger.LogFn(DebugLevel, fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) InfoFn(fn LogFunction) {
|
|
||||||
logger.LogFn(InfoLevel, fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) PrintFn(fn LogFunction) {
|
|
||||||
entry := logger.newEntry()
|
entry := logger.newEntry()
|
||||||
entry.Print(fn()...)
|
entry.Panic(args...)
|
||||||
logger.releaseEntry(entry)
|
logger.releaseEntry(entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) WarnFn(fn LogFunction) {
|
|
||||||
logger.LogFn(WarnLevel, fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) WarningFn(fn LogFunction) {
|
|
||||||
logger.WarnFn(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) ErrorFn(fn LogFunction) {
|
|
||||||
logger.LogFn(ErrorLevel, fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) FatalFn(fn LogFunction) {
|
|
||||||
logger.LogFn(FatalLevel, fn)
|
|
||||||
logger.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) PanicFn(fn LogFunction) {
|
|
||||||
logger.LogFn(PanicLevel, fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Logln(level Level, args ...interface{}) {
|
|
||||||
if logger.IsLevelEnabled(level) {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Logln(level, args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Traceln(args ...interface{}) {
|
|
||||||
logger.Logln(TraceLevel, args...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Debugln(args ...interface{}) {
|
func (logger *Logger) Debugln(args ...interface{}) {
|
||||||
logger.Logln(DebugLevel, args...)
|
if logger.level() >= DebugLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Debugln(args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Infoln(args ...interface{}) {
|
func (logger *Logger) Infoln(args ...interface{}) {
|
||||||
logger.Logln(InfoLevel, args...)
|
if logger.level() >= InfoLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Infoln(args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Println(args ...interface{}) {
|
func (logger *Logger) Println(args ...interface{}) {
|
||||||
|
@ -313,32 +261,44 @@ func (logger *Logger) Println(args ...interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Warnln(args ...interface{}) {
|
func (logger *Logger) Warnln(args ...interface{}) {
|
||||||
logger.Logln(WarnLevel, args...)
|
if logger.level() >= WarnLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Warnln(args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Warningln(args ...interface{}) {
|
func (logger *Logger) Warningln(args ...interface{}) {
|
||||||
logger.Warnln(args...)
|
if logger.level() >= WarnLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Warnln(args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Errorln(args ...interface{}) {
|
func (logger *Logger) Errorln(args ...interface{}) {
|
||||||
logger.Logln(ErrorLevel, args...)
|
if logger.level() >= ErrorLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Errorln(args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Fatalln(args ...interface{}) {
|
func (logger *Logger) Fatalln(args ...interface{}) {
|
||||||
logger.Logln(FatalLevel, args...)
|
if logger.level() >= FatalLevel {
|
||||||
logger.Exit(1)
|
entry := logger.newEntry()
|
||||||
|
entry.Fatalln(args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
|
}
|
||||||
|
Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Panicln(args ...interface{}) {
|
func (logger *Logger) Panicln(args ...interface{}) {
|
||||||
logger.Logln(PanicLevel, args...)
|
if logger.level() >= PanicLevel {
|
||||||
|
entry := logger.newEntry()
|
||||||
|
entry.Panicln(args...)
|
||||||
|
logger.releaseEntry(entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) Exit(code int) {
|
|
||||||
runHandlers()
|
|
||||||
if logger.ExitFunc == nil {
|
|
||||||
logger.ExitFunc = os.Exit
|
|
||||||
}
|
|
||||||
logger.ExitFunc(code)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//When file is opened with appending mode, it's safe to
|
//When file is opened with appending mode, it's safe to
|
||||||
|
@ -352,53 +312,6 @@ func (logger *Logger) level() Level {
|
||||||
return Level(atomic.LoadUint32((*uint32)(&logger.Level)))
|
return Level(atomic.LoadUint32((*uint32)(&logger.Level)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLevel sets the logger level.
|
|
||||||
func (logger *Logger) SetLevel(level Level) {
|
func (logger *Logger) SetLevel(level Level) {
|
||||||
atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
|
atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLevel returns the logger level.
|
|
||||||
func (logger *Logger) GetLevel() Level {
|
|
||||||
return logger.level()
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddHook adds a hook to the logger hooks.
|
|
||||||
func (logger *Logger) AddHook(hook Hook) {
|
|
||||||
logger.mu.Lock()
|
|
||||||
defer logger.mu.Unlock()
|
|
||||||
logger.Hooks.Add(hook)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsLevelEnabled checks if the log level of the logger is greater than the level param
|
|
||||||
func (logger *Logger) IsLevelEnabled(level Level) bool {
|
|
||||||
return logger.level() >= level
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetFormatter sets the logger formatter.
|
|
||||||
func (logger *Logger) SetFormatter(formatter Formatter) {
|
|
||||||
logger.mu.Lock()
|
|
||||||
defer logger.mu.Unlock()
|
|
||||||
logger.Formatter = formatter
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOutput sets the logger output.
|
|
||||||
func (logger *Logger) SetOutput(output io.Writer) {
|
|
||||||
logger.mu.Lock()
|
|
||||||
defer logger.mu.Unlock()
|
|
||||||
logger.Out = output
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) SetReportCaller(reportCaller bool) {
|
|
||||||
logger.mu.Lock()
|
|
||||||
defer logger.mu.Unlock()
|
|
||||||
logger.ReportCaller = reportCaller
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReplaceHooks replaces the logger hooks and returns the old ones
|
|
||||||
func (logger *Logger) ReplaceHooks(hooks LevelHooks) LevelHooks {
|
|
||||||
logger.mu.Lock()
|
|
||||||
oldHooks := logger.Hooks
|
|
||||||
logger.Hooks = hooks
|
|
||||||
logger.mu.Unlock()
|
|
||||||
return oldHooks
|
|
||||||
}
|
|
||||||
|
|
61
vendor/github.com/sirupsen/logrus/logger_bench_test.go
generated
vendored
Normal file
61
vendor/github.com/sirupsen/logrus/logger_bench_test.go
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package logrus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// smallFields is a small size data set for benchmarking
|
||||||
|
var loggerFields = Fields{
|
||||||
|
"foo": "bar",
|
||||||
|
"baz": "qux",
|
||||||
|
"one": "two",
|
||||||
|
"three": "four",
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDummyLogger(b *testing.B) {
|
||||||
|
nullf, err := os.OpenFile("/dev/null", os.O_WRONLY, 0666)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
defer nullf.Close()
|
||||||
|
doLoggerBenchmark(b, nullf, &TextFormatter{DisableColors: true}, smallFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDummyLoggerNoLock(b *testing.B) {
|
||||||
|
nullf, err := os.OpenFile("/dev/null", os.O_WRONLY|os.O_APPEND, 0666)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
defer nullf.Close()
|
||||||
|
doLoggerBenchmarkNoLock(b, nullf, &TextFormatter{DisableColors: true}, smallFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
func doLoggerBenchmark(b *testing.B, out *os.File, formatter Formatter, fields Fields) {
|
||||||
|
logger := Logger{
|
||||||
|
Out: out,
|
||||||
|
Level: InfoLevel,
|
||||||
|
Formatter: formatter,
|
||||||
|
}
|
||||||
|
entry := logger.WithFields(fields)
|
||||||
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
|
for pb.Next() {
|
||||||
|
entry.Info("aaa")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func doLoggerBenchmarkNoLock(b *testing.B, out *os.File, formatter Formatter, fields Fields) {
|
||||||
|
logger := Logger{
|
||||||
|
Out: out,
|
||||||
|
Level: InfoLevel,
|
||||||
|
Formatter: formatter,
|
||||||
|
}
|
||||||
|
logger.SetNoLock()
|
||||||
|
entry := logger.WithFields(fields)
|
||||||
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
|
for pb.Next() {
|
||||||
|
entry.Info("aaa")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
75
vendor/github.com/sirupsen/logrus/logrus.go
generated
vendored
75
vendor/github.com/sirupsen/logrus/logrus.go
generated
vendored
|
@ -14,11 +14,22 @@ type Level uint32
|
||||||
|
|
||||||
// Convert the Level to a string. E.g. PanicLevel becomes "panic".
|
// Convert the Level to a string. E.g. PanicLevel becomes "panic".
|
||||||
func (level Level) String() string {
|
func (level Level) String() string {
|
||||||
if b, err := level.MarshalText(); err == nil {
|
switch level {
|
||||||
return string(b)
|
case DebugLevel:
|
||||||
} else {
|
return "debug"
|
||||||
return "unknown"
|
case InfoLevel:
|
||||||
|
return "info"
|
||||||
|
case WarnLevel:
|
||||||
|
return "warning"
|
||||||
|
case ErrorLevel:
|
||||||
|
return "error"
|
||||||
|
case FatalLevel:
|
||||||
|
return "fatal"
|
||||||
|
case PanicLevel:
|
||||||
|
return "panic"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return "unknown"
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseLevel takes a string level and returns the Logrus log level constant.
|
// ParseLevel takes a string level and returns the Logrus log level constant.
|
||||||
|
@ -36,47 +47,12 @@ func ParseLevel(lvl string) (Level, error) {
|
||||||
return InfoLevel, nil
|
return InfoLevel, nil
|
||||||
case "debug":
|
case "debug":
|
||||||
return DebugLevel, nil
|
return DebugLevel, nil
|
||||||
case "trace":
|
|
||||||
return TraceLevel, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var l Level
|
var l Level
|
||||||
return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
|
return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalText implements encoding.TextUnmarshaler.
|
|
||||||
func (level *Level) UnmarshalText(text []byte) error {
|
|
||||||
l, err := ParseLevel(string(text))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
*level = l
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (level Level) MarshalText() ([]byte, error) {
|
|
||||||
switch level {
|
|
||||||
case TraceLevel:
|
|
||||||
return []byte("trace"), nil
|
|
||||||
case DebugLevel:
|
|
||||||
return []byte("debug"), nil
|
|
||||||
case InfoLevel:
|
|
||||||
return []byte("info"), nil
|
|
||||||
case WarnLevel:
|
|
||||||
return []byte("warning"), nil
|
|
||||||
case ErrorLevel:
|
|
||||||
return []byte("error"), nil
|
|
||||||
case FatalLevel:
|
|
||||||
return []byte("fatal"), nil
|
|
||||||
case PanicLevel:
|
|
||||||
return []byte("panic"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("not a valid logrus level %d", level)
|
|
||||||
}
|
|
||||||
|
|
||||||
// A constant exposing all logging levels
|
// A constant exposing all logging levels
|
||||||
var AllLevels = []Level{
|
var AllLevels = []Level{
|
||||||
PanicLevel,
|
PanicLevel,
|
||||||
|
@ -85,7 +61,6 @@ var AllLevels = []Level{
|
||||||
WarnLevel,
|
WarnLevel,
|
||||||
InfoLevel,
|
InfoLevel,
|
||||||
DebugLevel,
|
DebugLevel,
|
||||||
TraceLevel,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are the different logging levels. You can set the logging level to log
|
// These are the different logging levels. You can set the logging level to log
|
||||||
|
@ -94,7 +69,7 @@ const (
|
||||||
// PanicLevel level, highest level of severity. Logs and then calls panic with the
|
// PanicLevel level, highest level of severity. Logs and then calls panic with the
|
||||||
// message passed to Debug, Info, ...
|
// message passed to Debug, Info, ...
|
||||||
PanicLevel Level = iota
|
PanicLevel Level = iota
|
||||||
// FatalLevel level. Logs and then calls `logger.Exit(1)`. It will exit even if the
|
// FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
|
||||||
// logging level is set to Panic.
|
// logging level is set to Panic.
|
||||||
FatalLevel
|
FatalLevel
|
||||||
// ErrorLevel level. Logs. Used for errors that should definitely be noted.
|
// ErrorLevel level. Logs. Used for errors that should definitely be noted.
|
||||||
|
@ -107,8 +82,6 @@ const (
|
||||||
InfoLevel
|
InfoLevel
|
||||||
// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
|
// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
|
||||||
DebugLevel
|
DebugLevel
|
||||||
// TraceLevel level. Designates finer-grained informational events than the Debug.
|
|
||||||
TraceLevel
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Won't compile if StdLogger can't be realized by a log.Logger
|
// Won't compile if StdLogger can't be realized by a log.Logger
|
||||||
|
@ -167,20 +140,4 @@ type FieldLogger interface {
|
||||||
Errorln(args ...interface{})
|
Errorln(args ...interface{})
|
||||||
Fatalln(args ...interface{})
|
Fatalln(args ...interface{})
|
||||||
Panicln(args ...interface{})
|
Panicln(args ...interface{})
|
||||||
|
|
||||||
// IsDebugEnabled() bool
|
|
||||||
// IsInfoEnabled() bool
|
|
||||||
// IsWarnEnabled() bool
|
|
||||||
// IsErrorEnabled() bool
|
|
||||||
// IsFatalEnabled() bool
|
|
||||||
// IsPanicEnabled() bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ext1FieldLogger (the first extension to FieldLogger) is superfluous, it is
|
|
||||||
// here for consistancy. Do not use. Use Logger or Entry instead.
|
|
||||||
type Ext1FieldLogger interface {
|
|
||||||
FieldLogger
|
|
||||||
Tracef(format string, args ...interface{})
|
|
||||||
Trace(args ...interface{})
|
|
||||||
Traceln(args ...interface{})
|
|
||||||
}
|
}
|
||||||
|
|
386
vendor/github.com/sirupsen/logrus/logrus_test.go
generated
vendored
Normal file
386
vendor/github.com/sirupsen/logrus/logrus_test.go
generated
vendored
Normal file
|
@ -0,0 +1,386 @@
|
||||||
|
package logrus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LogAndAssertJSON(t *testing.T, log func(*Logger), assertions func(fields Fields)) {
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
var fields Fields
|
||||||
|
|
||||||
|
logger := New()
|
||||||
|
logger.Out = &buffer
|
||||||
|
logger.Formatter = new(JSONFormatter)
|
||||||
|
|
||||||
|
log(logger)
|
||||||
|
|
||||||
|
err := json.Unmarshal(buffer.Bytes(), &fields)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
assertions(fields)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LogAndAssertText(t *testing.T, log func(*Logger), assertions func(fields map[string]string)) {
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
|
||||||
|
logger := New()
|
||||||
|
logger.Out = &buffer
|
||||||
|
logger.Formatter = &TextFormatter{
|
||||||
|
DisableColors: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
log(logger)
|
||||||
|
|
||||||
|
fields := make(map[string]string)
|
||||||
|
for _, kv := range strings.Split(buffer.String(), " ") {
|
||||||
|
if !strings.Contains(kv, "=") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
kvArr := strings.Split(kv, "=")
|
||||||
|
key := strings.TrimSpace(kvArr[0])
|
||||||
|
val := kvArr[1]
|
||||||
|
if kvArr[1][0] == '"' {
|
||||||
|
var err error
|
||||||
|
val, err = strconv.Unquote(val)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
fields[key] = val
|
||||||
|
}
|
||||||
|
assertions(fields)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrint(t *testing.T) {
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.Print("test")
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["msg"], "test")
|
||||||
|
assert.Equal(t, fields["level"], "info")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInfo(t *testing.T) {
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.Info("test")
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["msg"], "test")
|
||||||
|
assert.Equal(t, fields["level"], "info")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWarn(t *testing.T) {
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.Warn("test")
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["msg"], "test")
|
||||||
|
assert.Equal(t, fields["level"], "warning")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) {
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.Infoln("test", "test")
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["msg"], "test test")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) {
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.Infoln("test", 10)
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["msg"], "test 10")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.Infoln(10, 10)
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["msg"], "10 10")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.Infoln(10, 10)
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["msg"], "10 10")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) {
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.Info("test", 10)
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["msg"], "test10")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) {
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.Info("test", "test")
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["msg"], "testtest")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithFieldsShouldAllowAssignments(t *testing.T) {
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
var fields Fields
|
||||||
|
|
||||||
|
logger := New()
|
||||||
|
logger.Out = &buffer
|
||||||
|
logger.Formatter = new(JSONFormatter)
|
||||||
|
|
||||||
|
localLog := logger.WithFields(Fields{
|
||||||
|
"key1": "value1",
|
||||||
|
})
|
||||||
|
|
||||||
|
localLog.WithField("key2", "value2").Info("test")
|
||||||
|
err := json.Unmarshal(buffer.Bytes(), &fields)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, "value2", fields["key2"])
|
||||||
|
assert.Equal(t, "value1", fields["key1"])
|
||||||
|
|
||||||
|
buffer = bytes.Buffer{}
|
||||||
|
fields = Fields{}
|
||||||
|
localLog.Info("test")
|
||||||
|
err = json.Unmarshal(buffer.Bytes(), &fields)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
_, ok := fields["key2"]
|
||||||
|
assert.Equal(t, false, ok)
|
||||||
|
assert.Equal(t, "value1", fields["key1"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUserSuppliedFieldDoesNotOverwriteDefaults(t *testing.T) {
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.WithField("msg", "hello").Info("test")
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["msg"], "test")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUserSuppliedMsgFieldHasPrefix(t *testing.T) {
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.WithField("msg", "hello").Info("test")
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["msg"], "test")
|
||||||
|
assert.Equal(t, fields["fields.msg"], "hello")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUserSuppliedTimeFieldHasPrefix(t *testing.T) {
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.WithField("time", "hello").Info("test")
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["fields.time"], "hello")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) {
|
||||||
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
|
log.WithField("level", 1).Info("test")
|
||||||
|
}, func(fields Fields) {
|
||||||
|
assert.Equal(t, fields["level"], "info")
|
||||||
|
assert.Equal(t, fields["fields.level"], 1.0) // JSON has floats only
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultFieldsAreNotPrefixed(t *testing.T) {
|
||||||
|
LogAndAssertText(t, func(log *Logger) {
|
||||||
|
ll := log.WithField("herp", "derp")
|
||||||
|
ll.Info("hello")
|
||||||
|
ll.Info("bye")
|
||||||
|
}, func(fields map[string]string) {
|
||||||
|
for _, fieldName := range []string{"fields.level", "fields.time", "fields.msg"} {
|
||||||
|
if _, ok := fields[fieldName]; ok {
|
||||||
|
t.Fatalf("should not have prefixed %q: %v", fieldName, fields)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) {
|
||||||
|
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
var fields Fields
|
||||||
|
|
||||||
|
logger := New()
|
||||||
|
logger.Out = &buffer
|
||||||
|
logger.Formatter = new(JSONFormatter)
|
||||||
|
|
||||||
|
llog := logger.WithField("context", "eating raw fish")
|
||||||
|
|
||||||
|
llog.Info("looks delicious")
|
||||||
|
|
||||||
|
err := json.Unmarshal(buffer.Bytes(), &fields)
|
||||||
|
assert.NoError(t, err, "should have decoded first message")
|
||||||
|
assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
|
||||||
|
assert.Equal(t, fields["msg"], "looks delicious")
|
||||||
|
assert.Equal(t, fields["context"], "eating raw fish")
|
||||||
|
|
||||||
|
buffer.Reset()
|
||||||
|
|
||||||
|
llog.Warn("omg it is!")
|
||||||
|
|
||||||
|
err = json.Unmarshal(buffer.Bytes(), &fields)
|
||||||
|
assert.NoError(t, err, "should have decoded second message")
|
||||||
|
assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
|
||||||
|
assert.Equal(t, fields["msg"], "omg it is!")
|
||||||
|
assert.Equal(t, fields["context"], "eating raw fish")
|
||||||
|
assert.Nil(t, fields["fields.msg"], "should not have prefixed previous `msg` entry")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConvertLevelToString(t *testing.T) {
|
||||||
|
assert.Equal(t, "debug", DebugLevel.String())
|
||||||
|
assert.Equal(t, "info", InfoLevel.String())
|
||||||
|
assert.Equal(t, "warning", WarnLevel.String())
|
||||||
|
assert.Equal(t, "error", ErrorLevel.String())
|
||||||
|
assert.Equal(t, "fatal", FatalLevel.String())
|
||||||
|
assert.Equal(t, "panic", PanicLevel.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseLevel(t *testing.T) {
|
||||||
|
l, err := ParseLevel("panic")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, PanicLevel, l)
|
||||||
|
|
||||||
|
l, err = ParseLevel("PANIC")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, PanicLevel, l)
|
||||||
|
|
||||||
|
l, err = ParseLevel("fatal")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, FatalLevel, l)
|
||||||
|
|
||||||
|
l, err = ParseLevel("FATAL")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, FatalLevel, l)
|
||||||
|
|
||||||
|
l, err = ParseLevel("error")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, ErrorLevel, l)
|
||||||
|
|
||||||
|
l, err = ParseLevel("ERROR")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, ErrorLevel, l)
|
||||||
|
|
||||||
|
l, err = ParseLevel("warn")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, WarnLevel, l)
|
||||||
|
|
||||||
|
l, err = ParseLevel("WARN")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, WarnLevel, l)
|
||||||
|
|
||||||
|
l, err = ParseLevel("warning")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, WarnLevel, l)
|
||||||
|
|
||||||
|
l, err = ParseLevel("WARNING")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, WarnLevel, l)
|
||||||
|
|
||||||
|
l, err = ParseLevel("info")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, InfoLevel, l)
|
||||||
|
|
||||||
|
l, err = ParseLevel("INFO")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, InfoLevel, l)
|
||||||
|
|
||||||
|
l, err = ParseLevel("debug")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, DebugLevel, l)
|
||||||
|
|
||||||
|
l, err = ParseLevel("DEBUG")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, DebugLevel, l)
|
||||||
|
|
||||||
|
l, err = ParseLevel("invalid")
|
||||||
|
assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetSetLevelRace(t *testing.T) {
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(i int) {
|
||||||
|
defer wg.Done()
|
||||||
|
if i%2 == 0 {
|
||||||
|
SetLevel(InfoLevel)
|
||||||
|
} else {
|
||||||
|
GetLevel()
|
||||||
|
}
|
||||||
|
}(i)
|
||||||
|
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoggingRace(t *testing.T) {
|
||||||
|
logger := New()
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(100)
|
||||||
|
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
go func() {
|
||||||
|
logger.Info("info")
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile test
|
||||||
|
func TestLogrusInterface(t *testing.T) {
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
fn := func(l FieldLogger) {
|
||||||
|
b := l.WithField("key", "value")
|
||||||
|
b.Debug("Test")
|
||||||
|
}
|
||||||
|
// test logger
|
||||||
|
logger := New()
|
||||||
|
logger.Out = &buffer
|
||||||
|
fn(logger)
|
||||||
|
|
||||||
|
// test Entry
|
||||||
|
e := logger.WithField("another", "value")
|
||||||
|
fn(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements io.Writer using channels for synchronization, so we can wait on
|
||||||
|
// the Entry.Writer goroutine to write in a non-racey way. This does assume that
|
||||||
|
// there is a single call to Logger.Out for each message.
|
||||||
|
type channelWriter chan []byte
|
||||||
|
|
||||||
|
func (cw channelWriter) Write(p []byte) (int, error) {
|
||||||
|
cw <- p
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEntryWriter(t *testing.T) {
|
||||||
|
cw := channelWriter(make(chan []byte, 1))
|
||||||
|
log := New()
|
||||||
|
log.Out = cw
|
||||||
|
log.Formatter = new(JSONFormatter)
|
||||||
|
log.WithField("foo", "bar").WriterLevel(WarnLevel).Write([]byte("hello\n"))
|
||||||
|
|
||||||
|
bs := <-cw
|
||||||
|
var fields Fields
|
||||||
|
err := json.Unmarshal(bs, &fields)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, fields["foo"], "bar")
|
||||||
|
assert.Equal(t, fields["level"], "warning")
|
||||||
|
}
|
10
vendor/github.com/sirupsen/logrus/terminal_bsd.go
generated
vendored
Normal file
10
vendor/github.com/sirupsen/logrus/terminal_bsd.go
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// +build darwin freebsd openbsd netbsd dragonfly
|
||||||
|
// +build !appengine
|
||||||
|
|
||||||
|
package logrus
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
const ioctlReadTermios = unix.TIOCGETA
|
||||||
|
|
||||||
|
type Termios unix.Termios
|
11
vendor/github.com/sirupsen/logrus/terminal_check_appengine.go
generated
vendored
11
vendor/github.com/sirupsen/logrus/terminal_check_appengine.go
generated
vendored
|
@ -1,11 +0,0 @@
|
||||||
// +build appengine
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
func checkIfTerminal(w io.Writer) bool {
|
|
||||||
return true
|
|
||||||
}
|
|
13
vendor/github.com/sirupsen/logrus/terminal_check_bsd.go
generated
vendored
13
vendor/github.com/sirupsen/logrus/terminal_check_bsd.go
generated
vendored
|
@ -1,13 +0,0 @@
|
||||||
// +build darwin dragonfly freebsd netbsd openbsd
|
|
||||||
// +build !js
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import "golang.org/x/sys/unix"
|
|
||||||
|
|
||||||
const ioctlReadTermios = unix.TIOCGETA
|
|
||||||
|
|
||||||
func isTerminal(fd int) bool {
|
|
||||||
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
7
vendor/github.com/sirupsen/logrus/terminal_check_js.go
generated
vendored
7
vendor/github.com/sirupsen/logrus/terminal_check_js.go
generated
vendored
|
@ -1,7 +0,0 @@
|
||||||
// +build js
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
func isTerminal(fd int) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
11
vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go
generated
vendored
11
vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go
generated
vendored
|
@ -1,11 +0,0 @@
|
||||||
// +build js nacl plan9
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
func checkIfTerminal(w io.Writer) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
17
vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go
generated
vendored
17
vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go
generated
vendored
|
@ -1,17 +0,0 @@
|
||||||
// +build !appengine,!js,!windows,!nacl,!plan9
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func checkIfTerminal(w io.Writer) bool {
|
|
||||||
switch v := w.(type) {
|
|
||||||
case *os.File:
|
|
||||||
return isTerminal(int(v.Fd()))
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
11
vendor/github.com/sirupsen/logrus/terminal_check_solaris.go
generated
vendored
11
vendor/github.com/sirupsen/logrus/terminal_check_solaris.go
generated
vendored
|
@ -1,11 +0,0 @@
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
|
||||||
func isTerminal(fd int) bool {
|
|
||||||
_, err := unix.IoctlGetTermio(fd, unix.TCGETA)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
13
vendor/github.com/sirupsen/logrus/terminal_check_unix.go
generated
vendored
13
vendor/github.com/sirupsen/logrus/terminal_check_unix.go
generated
vendored
|
@ -1,13 +0,0 @@
|
||||||
// +build linux aix
|
|
||||||
// +build !js
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import "golang.org/x/sys/unix"
|
|
||||||
|
|
||||||
const ioctlReadTermios = unix.TCGETS
|
|
||||||
|
|
||||||
func isTerminal(fd int) bool {
|
|
||||||
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
27
vendor/github.com/sirupsen/logrus/terminal_check_windows.go
generated
vendored
27
vendor/github.com/sirupsen/logrus/terminal_check_windows.go
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
// +build !appengine,!js,windows
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
|
||||||
|
|
||||||
func checkIfTerminal(w io.Writer) bool {
|
|
||||||
switch v := w.(type) {
|
|
||||||
case *os.File:
|
|
||||||
handle := windows.Handle(v.Fd())
|
|
||||||
var mode uint32
|
|
||||||
if err := windows.GetConsoleMode(handle, &mode); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
mode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
|
||||||
if err := windows.SetConsoleMode(handle, mode); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
14
vendor/github.com/sirupsen/logrus/terminal_linux.go
generated
vendored
Normal file
14
vendor/github.com/sirupsen/logrus/terminal_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Based on ssh/terminal:
|
||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !appengine
|
||||||
|
|
||||||
|
package logrus
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
const ioctlReadTermios = unix.TCGETS
|
||||||
|
|
||||||
|
type Termios unix.Termios
|
231
vendor/github.com/sirupsen/logrus/text_formatter.go
generated
vendored
231
vendor/github.com/sirupsen/logrus/text_formatter.go
generated
vendored
|
@ -3,24 +3,28 @@ package logrus
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
"unicode/utf8"
|
|
||||||
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
nocolor = 0
|
||||||
red = 31
|
red = 31
|
||||||
|
green = 32
|
||||||
yellow = 33
|
yellow = 33
|
||||||
blue = 36
|
blue = 36
|
||||||
gray = 37
|
gray = 37
|
||||||
)
|
)
|
||||||
|
|
||||||
var baseTimestamp time.Time
|
var (
|
||||||
|
baseTimestamp time.Time
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
baseTimestamp = time.Now()
|
baseTimestamp = time.Now()
|
||||||
|
@ -34,17 +38,6 @@ type TextFormatter struct {
|
||||||
// Force disabling colors.
|
// Force disabling colors.
|
||||||
DisableColors bool
|
DisableColors bool
|
||||||
|
|
||||||
// Force quoting of all values
|
|
||||||
ForceQuote bool
|
|
||||||
|
|
||||||
// DisableQuote disables quoting for all values.
|
|
||||||
// DisableQuote will have a lower priority than ForceQuote.
|
|
||||||
// If both of them are set to true, quote will be forced on all values.
|
|
||||||
DisableQuote bool
|
|
||||||
|
|
||||||
// Override coloring based on CLICOLOR and CLICOLOR_FORCE. - https://bixense.com/clicolors/
|
|
||||||
EnvironmentOverrideColors bool
|
|
||||||
|
|
||||||
// Disable timestamp logging. useful when output is redirected to logging
|
// Disable timestamp logging. useful when output is redirected to logging
|
||||||
// system that already adds timestamps.
|
// system that already adds timestamps.
|
||||||
DisableTimestamp bool
|
DisableTimestamp bool
|
||||||
|
@ -61,164 +54,69 @@ type TextFormatter struct {
|
||||||
// be desired.
|
// be desired.
|
||||||
DisableSorting bool
|
DisableSorting bool
|
||||||
|
|
||||||
// The keys sorting function, when uninitialized it uses sort.Strings.
|
|
||||||
SortingFunc func([]string)
|
|
||||||
|
|
||||||
// Disables the truncation of the level text to 4 characters.
|
|
||||||
DisableLevelTruncation bool
|
|
||||||
|
|
||||||
// PadLevelText Adds padding the level text so that all the levels output at the same length
|
|
||||||
// PadLevelText is a superset of the DisableLevelTruncation option
|
|
||||||
PadLevelText bool
|
|
||||||
|
|
||||||
// QuoteEmptyFields will wrap empty fields in quotes if true
|
// QuoteEmptyFields will wrap empty fields in quotes if true
|
||||||
QuoteEmptyFields bool
|
QuoteEmptyFields bool
|
||||||
|
|
||||||
// Whether the logger's out is to a terminal
|
// Whether the logger's out is to a terminal
|
||||||
isTerminal bool
|
isTerminal bool
|
||||||
|
|
||||||
// FieldMap allows users to customize the names of keys for default fields.
|
sync.Once
|
||||||
// As an example:
|
|
||||||
// formatter := &TextFormatter{
|
|
||||||
// FieldMap: FieldMap{
|
|
||||||
// FieldKeyTime: "@timestamp",
|
|
||||||
// FieldKeyLevel: "@level",
|
|
||||||
// FieldKeyMsg: "@message"}}
|
|
||||||
FieldMap FieldMap
|
|
||||||
|
|
||||||
// CallerPrettyfier can be set by the user to modify the content
|
|
||||||
// of the function and file keys in the data when ReportCaller is
|
|
||||||
// activated. If any of the returned value is the empty string the
|
|
||||||
// corresponding key will be removed from fields.
|
|
||||||
CallerPrettyfier func(*runtime.Frame) (function string, file string)
|
|
||||||
|
|
||||||
terminalInitOnce sync.Once
|
|
||||||
|
|
||||||
// The max length of the level text, generated dynamically on init
|
|
||||||
levelTextMaxLength int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *TextFormatter) init(entry *Entry) {
|
func (f *TextFormatter) init(entry *Entry) {
|
||||||
if entry.Logger != nil {
|
if entry.Logger != nil {
|
||||||
f.isTerminal = checkIfTerminal(entry.Logger.Out)
|
f.isTerminal = f.checkIfTerminal(entry.Logger.Out)
|
||||||
}
|
|
||||||
// Get the max length of the level text
|
|
||||||
for _, level := range AllLevels {
|
|
||||||
levelTextLength := utf8.RuneCount([]byte(level.String()))
|
|
||||||
if levelTextLength > f.levelTextMaxLength {
|
|
||||||
f.levelTextMaxLength = levelTextLength
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *TextFormatter) isColored() bool {
|
|
||||||
isColored := f.ForceColors || (f.isTerminal && (runtime.GOOS != "windows"))
|
|
||||||
|
|
||||||
if f.EnvironmentOverrideColors {
|
|
||||||
switch force, ok := os.LookupEnv("CLICOLOR_FORCE"); {
|
|
||||||
case ok && force != "0":
|
|
||||||
isColored = true
|
|
||||||
case ok && force == "0", os.Getenv("CLICOLOR") == "0":
|
|
||||||
isColored = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return isColored && !f.DisableColors
|
func (f *TextFormatter) checkIfTerminal(w io.Writer) bool {
|
||||||
|
switch v := w.(type) {
|
||||||
|
case *os.File:
|
||||||
|
return terminal.IsTerminal(int(v.Fd()))
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format renders a single log entry
|
// Format renders a single log entry
|
||||||
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
||||||
data := make(Fields)
|
var b *bytes.Buffer
|
||||||
for k, v := range entry.Data {
|
keys := make([]string, 0, len(entry.Data))
|
||||||
data[k] = v
|
for k := range entry.Data {
|
||||||
}
|
|
||||||
prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
|
|
||||||
keys := make([]string, 0, len(data))
|
|
||||||
for k := range data {
|
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
var funcVal, fileVal string
|
|
||||||
|
|
||||||
fixedKeys := make([]string, 0, 4+len(data))
|
|
||||||
if !f.DisableTimestamp {
|
|
||||||
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyTime))
|
|
||||||
}
|
|
||||||
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLevel))
|
|
||||||
if entry.Message != "" {
|
|
||||||
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyMsg))
|
|
||||||
}
|
|
||||||
if entry.err != "" {
|
|
||||||
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLogrusError))
|
|
||||||
}
|
|
||||||
if entry.HasCaller() {
|
|
||||||
if f.CallerPrettyfier != nil {
|
|
||||||
funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
|
|
||||||
} else {
|
|
||||||
funcVal = entry.Caller.Function
|
|
||||||
fileVal = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
|
|
||||||
}
|
|
||||||
|
|
||||||
if funcVal != "" {
|
|
||||||
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyFunc))
|
|
||||||
}
|
|
||||||
if fileVal != "" {
|
|
||||||
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyFile))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !f.DisableSorting {
|
if !f.DisableSorting {
|
||||||
if f.SortingFunc == nil {
|
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
fixedKeys = append(fixedKeys, keys...)
|
|
||||||
} else {
|
|
||||||
if !f.isColored() {
|
|
||||||
fixedKeys = append(fixedKeys, keys...)
|
|
||||||
f.SortingFunc(fixedKeys)
|
|
||||||
} else {
|
|
||||||
f.SortingFunc(keys)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fixedKeys = append(fixedKeys, keys...)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b *bytes.Buffer
|
|
||||||
if entry.Buffer != nil {
|
if entry.Buffer != nil {
|
||||||
b = entry.Buffer
|
b = entry.Buffer
|
||||||
} else {
|
} else {
|
||||||
b = &bytes.Buffer{}
|
b = &bytes.Buffer{}
|
||||||
}
|
}
|
||||||
|
|
||||||
f.terminalInitOnce.Do(func() { f.init(entry) })
|
prefixFieldClashes(entry.Data)
|
||||||
|
|
||||||
|
f.Do(func() { f.init(entry) })
|
||||||
|
|
||||||
|
isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors
|
||||||
|
|
||||||
timestampFormat := f.TimestampFormat
|
timestampFormat := f.TimestampFormat
|
||||||
if timestampFormat == "" {
|
if timestampFormat == "" {
|
||||||
timestampFormat = defaultTimestampFormat
|
timestampFormat = defaultTimestampFormat
|
||||||
}
|
}
|
||||||
if f.isColored() {
|
if isColored {
|
||||||
f.printColored(b, entry, keys, data, timestampFormat)
|
f.printColored(b, entry, keys, timestampFormat)
|
||||||
} else {
|
} else {
|
||||||
|
if !f.DisableTimestamp {
|
||||||
for _, key := range fixedKeys {
|
f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat))
|
||||||
var value interface{}
|
|
||||||
switch {
|
|
||||||
case key == f.FieldMap.resolve(FieldKeyTime):
|
|
||||||
value = entry.Time.Format(timestampFormat)
|
|
||||||
case key == f.FieldMap.resolve(FieldKeyLevel):
|
|
||||||
value = entry.Level.String()
|
|
||||||
case key == f.FieldMap.resolve(FieldKeyMsg):
|
|
||||||
value = entry.Message
|
|
||||||
case key == f.FieldMap.resolve(FieldKeyLogrusError):
|
|
||||||
value = entry.err
|
|
||||||
case key == f.FieldMap.resolve(FieldKeyFunc) && entry.HasCaller():
|
|
||||||
value = funcVal
|
|
||||||
case key == f.FieldMap.resolve(FieldKeyFile) && entry.HasCaller():
|
|
||||||
value = fileVal
|
|
||||||
default:
|
|
||||||
value = data[key]
|
|
||||||
}
|
}
|
||||||
f.appendKeyValue(b, key, value)
|
f.appendKeyValue(b, "level", entry.Level.String())
|
||||||
|
if entry.Message != "" {
|
||||||
|
f.appendKeyValue(b, "msg", entry.Message)
|
||||||
|
}
|
||||||
|
for _, key := range keys {
|
||||||
|
f.appendKeyValue(b, key, entry.Data[key])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,10 +124,10 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, data Fields, timestampFormat string) {
|
func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) {
|
||||||
var levelColor int
|
var levelColor int
|
||||||
switch entry.Level {
|
switch entry.Level {
|
||||||
case DebugLevel, TraceLevel:
|
case DebugLevel:
|
||||||
levelColor = gray
|
levelColor = gray
|
||||||
case WarnLevel:
|
case WarnLevel:
|
||||||
levelColor = yellow
|
levelColor = yellow
|
||||||
|
@ -239,67 +137,26 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
|
||||||
levelColor = blue
|
levelColor = blue
|
||||||
}
|
}
|
||||||
|
|
||||||
levelText := strings.ToUpper(entry.Level.String())
|
levelText := strings.ToUpper(entry.Level.String())[0:4]
|
||||||
if !f.DisableLevelTruncation && !f.PadLevelText {
|
|
||||||
levelText = levelText[0:4]
|
|
||||||
}
|
|
||||||
if f.PadLevelText {
|
|
||||||
// Generates the format string used in the next line, for example "%-6s" or "%-7s".
|
|
||||||
// Based on the max level text length.
|
|
||||||
formatString := "%-" + strconv.Itoa(f.levelTextMaxLength) + "s"
|
|
||||||
// Formats the level text by appending spaces up to the max length, for example:
|
|
||||||
// - "INFO "
|
|
||||||
// - "WARNING"
|
|
||||||
levelText = fmt.Sprintf(formatString, levelText)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove a single newline if it already exists in the message to keep
|
if f.DisableTimestamp {
|
||||||
// the behavior of logrus text_formatter the same as the stdlib log package
|
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m %-44s ", levelColor, levelText, entry.Message)
|
||||||
entry.Message = strings.TrimSuffix(entry.Message, "\n")
|
} else if !f.FullTimestamp {
|
||||||
|
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), entry.Message)
|
||||||
caller := ""
|
|
||||||
if entry.HasCaller() {
|
|
||||||
funcVal := fmt.Sprintf("%s()", entry.Caller.Function)
|
|
||||||
fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
|
|
||||||
|
|
||||||
if f.CallerPrettyfier != nil {
|
|
||||||
funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
|
|
||||||
}
|
|
||||||
|
|
||||||
if fileVal == "" {
|
|
||||||
caller = funcVal
|
|
||||||
} else if funcVal == "" {
|
|
||||||
caller = fileVal
|
|
||||||
} else {
|
} else {
|
||||||
caller = fileVal + " " + funcVal
|
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case f.DisableTimestamp:
|
|
||||||
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m%s %-44s ", levelColor, levelText, caller, entry.Message)
|
|
||||||
case !f.FullTimestamp:
|
|
||||||
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d]%s %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), caller, entry.Message)
|
|
||||||
default:
|
|
||||||
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s]%s %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), caller, entry.Message)
|
|
||||||
}
|
}
|
||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
v := data[k]
|
v := entry.Data[k]
|
||||||
fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k)
|
fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k)
|
||||||
f.appendValue(b, v)
|
f.appendValue(b, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *TextFormatter) needsQuoting(text string) bool {
|
func (f *TextFormatter) needsQuoting(text string) bool {
|
||||||
if f.ForceQuote {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if f.QuoteEmptyFields && len(text) == 0 {
|
if f.QuoteEmptyFields && len(text) == 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if f.DisableQuote {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, ch := range text {
|
for _, ch := range text {
|
||||||
if !((ch >= 'a' && ch <= 'z') ||
|
if !((ch >= 'a' && ch <= 'z') ||
|
||||||
(ch >= 'A' && ch <= 'Z') ||
|
(ch >= 'A' && ch <= 'Z') ||
|
||||||
|
|
141
vendor/github.com/sirupsen/logrus/text_formatter_test.go
generated
vendored
Normal file
141
vendor/github.com/sirupsen/logrus/text_formatter_test.go
generated
vendored
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
package logrus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFormatting(t *testing.T) {
|
||||||
|
tf := &TextFormatter{DisableColors: true}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
value string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{`foo`, "time=\"0001-01-01T00:00:00Z\" level=panic test=foo\n"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
b, _ := tf.Format(WithField("test", tc.value))
|
||||||
|
|
||||||
|
if string(b) != tc.expected {
|
||||||
|
t.Errorf("formatting expected for %q (result was %q instead of %q)", tc.value, string(b), tc.expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQuoting(t *testing.T) {
|
||||||
|
tf := &TextFormatter{DisableColors: true}
|
||||||
|
|
||||||
|
checkQuoting := func(q bool, value interface{}) {
|
||||||
|
b, _ := tf.Format(WithField("test", value))
|
||||||
|
idx := bytes.Index(b, ([]byte)("test="))
|
||||||
|
cont := bytes.Contains(b[idx+5:], []byte("\""))
|
||||||
|
if cont != q {
|
||||||
|
if q {
|
||||||
|
t.Errorf("quoting expected for: %#v", value)
|
||||||
|
} else {
|
||||||
|
t.Errorf("quoting not expected for: %#v", value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkQuoting(false, "")
|
||||||
|
checkQuoting(false, "abcd")
|
||||||
|
checkQuoting(false, "v1.0")
|
||||||
|
checkQuoting(false, "1234567890")
|
||||||
|
checkQuoting(false, "/foobar")
|
||||||
|
checkQuoting(false, "foo_bar")
|
||||||
|
checkQuoting(false, "foo@bar")
|
||||||
|
checkQuoting(false, "foobar^")
|
||||||
|
checkQuoting(false, "+/-_^@f.oobar")
|
||||||
|
checkQuoting(true, "foobar$")
|
||||||
|
checkQuoting(true, "&foobar")
|
||||||
|
checkQuoting(true, "x y")
|
||||||
|
checkQuoting(true, "x,y")
|
||||||
|
checkQuoting(false, errors.New("invalid"))
|
||||||
|
checkQuoting(true, errors.New("invalid argument"))
|
||||||
|
|
||||||
|
// Test for quoting empty fields.
|
||||||
|
tf.QuoteEmptyFields = true
|
||||||
|
checkQuoting(true, "")
|
||||||
|
checkQuoting(false, "abcd")
|
||||||
|
checkQuoting(true, errors.New("invalid argument"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEscaping(t *testing.T) {
|
||||||
|
tf := &TextFormatter{DisableColors: true}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
value string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{`ba"r`, `ba\"r`},
|
||||||
|
{`ba'r`, `ba'r`},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
b, _ := tf.Format(WithField("test", tc.value))
|
||||||
|
if !bytes.Contains(b, []byte(tc.expected)) {
|
||||||
|
t.Errorf("escaping expected for %q (result was %q instead of %q)", tc.value, string(b), tc.expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEscaping_Interface(t *testing.T) {
|
||||||
|
tf := &TextFormatter{DisableColors: true}
|
||||||
|
|
||||||
|
ts := time.Now()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
value interface{}
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{ts, fmt.Sprintf("\"%s\"", ts.String())},
|
||||||
|
{errors.New("error: something went wrong"), "\"error: something went wrong\""},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
b, _ := tf.Format(WithField("test", tc.value))
|
||||||
|
if !bytes.Contains(b, []byte(tc.expected)) {
|
||||||
|
t.Errorf("escaping expected for %q (result was %q instead of %q)", tc.value, string(b), tc.expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimestampFormat(t *testing.T) {
|
||||||
|
checkTimeStr := func(format string) {
|
||||||
|
customFormatter := &TextFormatter{DisableColors: true, TimestampFormat: format}
|
||||||
|
customStr, _ := customFormatter.Format(WithField("test", "test"))
|
||||||
|
timeStart := bytes.Index(customStr, ([]byte)("time="))
|
||||||
|
timeEnd := bytes.Index(customStr, ([]byte)("level="))
|
||||||
|
timeStr := customStr[timeStart+5+len("\"") : timeEnd-1-len("\"")]
|
||||||
|
if format == "" {
|
||||||
|
format = time.RFC3339
|
||||||
|
}
|
||||||
|
_, e := time.Parse(format, (string)(timeStr))
|
||||||
|
if e != nil {
|
||||||
|
t.Errorf("time string \"%s\" did not match provided time format \"%s\": %s", timeStr, format, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkTimeStr("2006-01-02T15:04:05.000000000Z07:00")
|
||||||
|
checkTimeStr("Mon Jan _2 15:04:05 2006")
|
||||||
|
checkTimeStr("")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDisableTimestampWithColoredOutput(t *testing.T) {
|
||||||
|
tf := &TextFormatter{DisableTimestamp: true, ForceColors: true}
|
||||||
|
|
||||||
|
b, _ := tf.Format(WithField("test", "test"))
|
||||||
|
if strings.Contains(string(b), "[0000]") {
|
||||||
|
t.Error("timestamp not expected when DisableTimestamp is true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO add tests for sorting etc., this requires a parser for the text
|
||||||
|
// formatter output.
|
8
vendor/github.com/sirupsen/logrus/writer.go
generated
vendored
8
vendor/github.com/sirupsen/logrus/writer.go
generated
vendored
|
@ -6,16 +6,10 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Writer at INFO level. See WriterLevel for details.
|
|
||||||
func (logger *Logger) Writer() *io.PipeWriter {
|
func (logger *Logger) Writer() *io.PipeWriter {
|
||||||
return logger.WriterLevel(InfoLevel)
|
return logger.WriterLevel(InfoLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriterLevel returns an io.Writer that can be used to write arbitrary text to
|
|
||||||
// the logger at the given log level. Each line written to the writer will be
|
|
||||||
// printed in the usual way using formatters and hooks. The writer is part of an
|
|
||||||
// io.Pipe and it is the callers responsibility to close the writer when done.
|
|
||||||
// This can be used to override the standard library logger easily.
|
|
||||||
func (logger *Logger) WriterLevel(level Level) *io.PipeWriter {
|
func (logger *Logger) WriterLevel(level Level) *io.PipeWriter {
|
||||||
return NewEntry(logger).WriterLevel(level)
|
return NewEntry(logger).WriterLevel(level)
|
||||||
}
|
}
|
||||||
|
@ -30,8 +24,6 @@ func (entry *Entry) WriterLevel(level Level) *io.PipeWriter {
|
||||||
var printFunc func(args ...interface{})
|
var printFunc func(args ...interface{})
|
||||||
|
|
||||||
switch level {
|
switch level {
|
||||||
case TraceLevel:
|
|
||||||
printFunc = entry.Trace
|
|
||||||
case DebugLevel:
|
case DebugLevel:
|
||||||
printFunc = entry.Debug
|
printFunc = entry.Debug
|
||||||
case InfoLevel:
|
case InfoLevel:
|
||||||
|
|
10
vendor/golang.org/x/crypto/.gitattributes
generated
vendored
Normal file
10
vendor/golang.org/x/crypto/.gitattributes
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# Treat all files in this repo as binary, with no git magic updating
|
||||||
|
# line endings. Windows users contributing to Go will need to use a
|
||||||
|
# modern version of git and editors capable of LF line endings.
|
||||||
|
#
|
||||||
|
# We'll prevent accidental CRLF line endings from entering the repo
|
||||||
|
# via the git-review gofmt checks.
|
||||||
|
#
|
||||||
|
# See golang.org/issue/9281
|
||||||
|
|
||||||
|
* -text
|
2
vendor/golang.org/x/crypto/.gitignore
generated
vendored
Normal file
2
vendor/golang.org/x/crypto/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# Add no patterns to .hgignore except for files generated by the build.
|
||||||
|
last-change
|
2
vendor/golang.org/x/crypto/AUTHORS
generated
vendored
2
vendor/golang.org/x/crypto/AUTHORS
generated
vendored
|
@ -1,3 +1,3 @@
|
||||||
# This source code refers to The Go Authors for copyright purposes.
|
# This source code refers to The Go Authors for copyright purposes.
|
||||||
# The master list of authors is in the main Go distribution,
|
# The master list of authors is in the main Go distribution,
|
||||||
# visible at https://tip.golang.org/AUTHORS.
|
# visible at http://tip.golang.org/AUTHORS.
|
||||||
|
|
31
vendor/golang.org/x/crypto/CONTRIBUTING.md
generated
vendored
Normal file
31
vendor/golang.org/x/crypto/CONTRIBUTING.md
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# Contributing to Go
|
||||||
|
|
||||||
|
Go is an open source project.
|
||||||
|
|
||||||
|
It is the work of hundreds of contributors. We appreciate your help!
|
||||||
|
|
||||||
|
|
||||||
|
## Filing issues
|
||||||
|
|
||||||
|
When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
|
||||||
|
|
||||||
|
1. What version of Go are you using (`go version`)?
|
||||||
|
2. What operating system and processor architecture are you using?
|
||||||
|
3. What did you do?
|
||||||
|
4. What did you expect to see?
|
||||||
|
5. What did you see instead?
|
||||||
|
|
||||||
|
General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
|
||||||
|
The gophers there will answer or ask you to file an issue if you've tripped over a bug.
|
||||||
|
|
||||||
|
## Contributing code
|
||||||
|
|
||||||
|
Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
|
||||||
|
before sending patches.
|
||||||
|
|
||||||
|
**We do not accept GitHub pull requests**
|
||||||
|
(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review).
|
||||||
|
|
||||||
|
Unless otherwise noted, the Go source files are distributed under
|
||||||
|
the BSD-style license found in the LICENSE file.
|
||||||
|
|
2
vendor/golang.org/x/crypto/CONTRIBUTORS
generated
vendored
2
vendor/golang.org/x/crypto/CONTRIBUTORS
generated
vendored
|
@ -1,3 +1,3 @@
|
||||||
# This source code was written by the Go contributors.
|
# This source code was written by the Go contributors.
|
||||||
# The master list of contributors is in the main Go distribution,
|
# The master list of contributors is in the main Go distribution,
|
||||||
# visible at https://tip.golang.org/CONTRIBUTORS.
|
# visible at http://tip.golang.org/CONTRIBUTORS.
|
||||||
|
|
3
vendor/golang.org/x/crypto/README
generated
vendored
Normal file
3
vendor/golang.org/x/crypto/README
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
This repository holds supplementary Go cryptography libraries.
|
||||||
|
|
||||||
|
To submit changes to this repository, see http://golang.org/doc/contribute.html.
|
35
vendor/golang.org/x/crypto/bcrypt/base64.go
generated
vendored
Normal file
35
vendor/golang.org/x/crypto/bcrypt/base64.go
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bcrypt
|
||||||
|
|
||||||
|
import "encoding/base64"
|
||||||
|
|
||||||
|
const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||||
|
|
||||||
|
var bcEncoding = base64.NewEncoding(alphabet)
|
||||||
|
|
||||||
|
func base64Encode(src []byte) []byte {
|
||||||
|
n := bcEncoding.EncodedLen(len(src))
|
||||||
|
dst := make([]byte, n)
|
||||||
|
bcEncoding.Encode(dst, src)
|
||||||
|
for dst[n-1] == '=' {
|
||||||
|
n--
|
||||||
|
}
|
||||||
|
return dst[:n]
|
||||||
|
}
|
||||||
|
|
||||||
|
func base64Decode(src []byte) ([]byte, error) {
|
||||||
|
numOfEquals := 4 - (len(src) % 4)
|
||||||
|
for i := 0; i < numOfEquals; i++ {
|
||||||
|
src = append(src, '=')
|
||||||
|
}
|
||||||
|
|
||||||
|
dst := make([]byte, bcEncoding.DecodedLen(len(src)))
|
||||||
|
n, err := bcEncoding.Decode(dst, src)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dst[:n], nil
|
||||||
|
}
|
294
vendor/golang.org/x/crypto/bcrypt/bcrypt.go
generated
vendored
Normal file
294
vendor/golang.org/x/crypto/bcrypt/bcrypt.go
generated
vendored
Normal file
|
@ -0,0 +1,294 @@
|
||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing
|
||||||
|
// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
|
||||||
|
package bcrypt // import "golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
|
// The code is a port of Provos and Mazières's C implementation.
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/subtle"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/crypto/blowfish"
|
||||||
|
"io"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword
|
||||||
|
MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword
|
||||||
|
DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword
|
||||||
|
)
|
||||||
|
|
||||||
|
// The error returned from CompareHashAndPassword when a password and hash do
|
||||||
|
// not match.
|
||||||
|
var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password")
|
||||||
|
|
||||||
|
// The error returned from CompareHashAndPassword when a hash is too short to
|
||||||
|
// be a bcrypt hash.
|
||||||
|
var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password")
|
||||||
|
|
||||||
|
// The error returned from CompareHashAndPassword when a hash was created with
|
||||||
|
// a bcrypt algorithm newer than this implementation.
|
||||||
|
type HashVersionTooNewError byte
|
||||||
|
|
||||||
|
func (hv HashVersionTooNewError) Error() string {
|
||||||
|
return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The error returned from CompareHashAndPassword when a hash starts with something other than '$'
|
||||||
|
type InvalidHashPrefixError byte
|
||||||
|
|
||||||
|
func (ih InvalidHashPrefixError) Error() string {
|
||||||
|
return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih))
|
||||||
|
}
|
||||||
|
|
||||||
|
type InvalidCostError int
|
||||||
|
|
||||||
|
func (ic InvalidCostError) Error() string {
|
||||||
|
return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost))
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
majorVersion = '2'
|
||||||
|
minorVersion = 'a'
|
||||||
|
maxSaltSize = 16
|
||||||
|
maxCryptedHashSize = 23
|
||||||
|
encodedSaltSize = 22
|
||||||
|
encodedHashSize = 31
|
||||||
|
minHashSize = 59
|
||||||
|
)
|
||||||
|
|
||||||
|
// magicCipherData is an IV for the 64 Blowfish encryption calls in
|
||||||
|
// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes.
|
||||||
|
var magicCipherData = []byte{
|
||||||
|
0x4f, 0x72, 0x70, 0x68,
|
||||||
|
0x65, 0x61, 0x6e, 0x42,
|
||||||
|
0x65, 0x68, 0x6f, 0x6c,
|
||||||
|
0x64, 0x65, 0x72, 0x53,
|
||||||
|
0x63, 0x72, 0x79, 0x44,
|
||||||
|
0x6f, 0x75, 0x62, 0x74,
|
||||||
|
}
|
||||||
|
|
||||||
|
type hashed struct {
|
||||||
|
hash []byte
|
||||||
|
salt []byte
|
||||||
|
cost int // allowed range is MinCost to MaxCost
|
||||||
|
major byte
|
||||||
|
minor byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateFromPassword returns the bcrypt hash of the password at the given
|
||||||
|
// cost. If the cost given is less than MinCost, the cost will be set to
|
||||||
|
// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
|
||||||
|
// to compare the returned hashed password with its cleartext version.
|
||||||
|
func GenerateFromPassword(password []byte, cost int) ([]byte, error) {
|
||||||
|
p, err := newFromPassword(password, cost)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return p.Hash(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompareHashAndPassword compares a bcrypt hashed password with its possible
|
||||||
|
// plaintext equivalent. Returns nil on success, or an error on failure.
|
||||||
|
func CompareHashAndPassword(hashedPassword, password []byte) error {
|
||||||
|
p, err := newFromHash(hashedPassword)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
otherHash, err := bcrypt(password, p.cost, p.salt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
|
||||||
|
if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrMismatchedHashAndPassword
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cost returns the hashing cost used to create the given hashed
|
||||||
|
// password. When, in the future, the hashing cost of a password system needs
|
||||||
|
// to be increased in order to adjust for greater computational power, this
|
||||||
|
// function allows one to establish which passwords need to be updated.
|
||||||
|
func Cost(hashedPassword []byte) (int, error) {
|
||||||
|
p, err := newFromHash(hashedPassword)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return p.cost, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFromPassword(password []byte, cost int) (*hashed, error) {
|
||||||
|
if cost < MinCost {
|
||||||
|
cost = DefaultCost
|
||||||
|
}
|
||||||
|
p := new(hashed)
|
||||||
|
p.major = majorVersion
|
||||||
|
p.minor = minorVersion
|
||||||
|
|
||||||
|
err := checkCost(cost)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p.cost = cost
|
||||||
|
|
||||||
|
unencodedSalt := make([]byte, maxSaltSize)
|
||||||
|
_, err = io.ReadFull(rand.Reader, unencodedSalt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.salt = base64Encode(unencodedSalt)
|
||||||
|
hash, err := bcrypt(password, p.cost, p.salt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p.hash = hash
|
||||||
|
return p, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFromHash(hashedSecret []byte) (*hashed, error) {
|
||||||
|
if len(hashedSecret) < minHashSize {
|
||||||
|
return nil, ErrHashTooShort
|
||||||
|
}
|
||||||
|
p := new(hashed)
|
||||||
|
n, err := p.decodeVersion(hashedSecret)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hashedSecret = hashedSecret[n:]
|
||||||
|
n, err = p.decodeCost(hashedSecret)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hashedSecret = hashedSecret[n:]
|
||||||
|
|
||||||
|
// The "+2" is here because we'll have to append at most 2 '=' to the salt
|
||||||
|
// when base64 decoding it in expensiveBlowfishSetup().
|
||||||
|
p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2)
|
||||||
|
copy(p.salt, hashedSecret[:encodedSaltSize])
|
||||||
|
|
||||||
|
hashedSecret = hashedSecret[encodedSaltSize:]
|
||||||
|
p.hash = make([]byte, len(hashedSecret))
|
||||||
|
copy(p.hash, hashedSecret)
|
||||||
|
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) {
|
||||||
|
cipherData := make([]byte, len(magicCipherData))
|
||||||
|
copy(cipherData, magicCipherData)
|
||||||
|
|
||||||
|
c, err := expensiveBlowfishSetup(password, uint32(cost), salt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 24; i += 8 {
|
||||||
|
for j := 0; j < 64; j++ {
|
||||||
|
c.Encrypt(cipherData[i:i+8], cipherData[i:i+8])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bug compatibility with C bcrypt implementations. We only encode 23 of
|
||||||
|
// the 24 bytes encrypted.
|
||||||
|
hsh := base64Encode(cipherData[:maxCryptedHashSize])
|
||||||
|
return hsh, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) {
|
||||||
|
|
||||||
|
csalt, err := base64Decode(salt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bug compatibility with C bcrypt implementations. They use the trailing
|
||||||
|
// NULL in the key string during expansion.
|
||||||
|
ckey := append(key, 0)
|
||||||
|
|
||||||
|
c, err := blowfish.NewSaltedCipher(ckey, csalt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var i, rounds uint64
|
||||||
|
rounds = 1 << cost
|
||||||
|
for i = 0; i < rounds; i++ {
|
||||||
|
blowfish.ExpandKey(ckey, c)
|
||||||
|
blowfish.ExpandKey(csalt, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *hashed) Hash() []byte {
|
||||||
|
arr := make([]byte, 60)
|
||||||
|
arr[0] = '$'
|
||||||
|
arr[1] = p.major
|
||||||
|
n := 2
|
||||||
|
if p.minor != 0 {
|
||||||
|
arr[2] = p.minor
|
||||||
|
n = 3
|
||||||
|
}
|
||||||
|
arr[n] = '$'
|
||||||
|
n += 1
|
||||||
|
copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost)))
|
||||||
|
n += 2
|
||||||
|
arr[n] = '$'
|
||||||
|
n += 1
|
||||||
|
copy(arr[n:], p.salt)
|
||||||
|
n += encodedSaltSize
|
||||||
|
copy(arr[n:], p.hash)
|
||||||
|
n += encodedHashSize
|
||||||
|
return arr[:n]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *hashed) decodeVersion(sbytes []byte) (int, error) {
|
||||||
|
if sbytes[0] != '$' {
|
||||||
|
return -1, InvalidHashPrefixError(sbytes[0])
|
||||||
|
}
|
||||||
|
if sbytes[1] > majorVersion {
|
||||||
|
return -1, HashVersionTooNewError(sbytes[1])
|
||||||
|
}
|
||||||
|
p.major = sbytes[1]
|
||||||
|
n := 3
|
||||||
|
if sbytes[2] != '$' {
|
||||||
|
p.minor = sbytes[2]
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// sbytes should begin where decodeVersion left off.
|
||||||
|
func (p *hashed) decodeCost(sbytes []byte) (int, error) {
|
||||||
|
cost, err := strconv.Atoi(string(sbytes[0:2]))
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
err = checkCost(cost)
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
p.cost = cost
|
||||||
|
return 3, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *hashed) String() string {
|
||||||
|
return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkCost(cost int) error {
|
||||||
|
if cost < MinCost || cost > MaxCost {
|
||||||
|
return InvalidCostError(cost)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
226
vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
generated
vendored
Normal file
226
vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
generated
vendored
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bcrypt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBcryptingIsEasy(t *testing.T) {
|
||||||
|
pass := []byte("mypassword")
|
||||||
|
hp, err := GenerateFromPassword(pass, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GenerateFromPassword error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if CompareHashAndPassword(hp, pass) != nil {
|
||||||
|
t.Errorf("%v should hash %s correctly", hp, pass)
|
||||||
|
}
|
||||||
|
|
||||||
|
notPass := "notthepass"
|
||||||
|
err = CompareHashAndPassword(hp, []byte(notPass))
|
||||||
|
if err != ErrMismatchedHashAndPassword {
|
||||||
|
t.Errorf("%v and %s should be mismatched", hp, notPass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBcryptingIsCorrect(t *testing.T) {
|
||||||
|
pass := []byte("allmine")
|
||||||
|
salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
||||||
|
expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
|
||||||
|
|
||||||
|
hash, err := bcrypt(pass, 10, salt)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bcrypt blew up: %v", err)
|
||||||
|
}
|
||||||
|
if !bytes.HasSuffix(expectedHash, hash) {
|
||||||
|
t.Errorf("%v should be the suffix of %v", hash, expectedHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
h, err := newFromHash(expectedHash)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unable to parse %s: %v", string(expectedHash), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is not the safe way to compare these hashes. We do this only for
|
||||||
|
// testing clarity. Use bcrypt.CompareHashAndPassword()
|
||||||
|
if err == nil && !bytes.Equal(expectedHash, h.Hash()) {
|
||||||
|
t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVeryShortPasswords(t *testing.T) {
|
||||||
|
key := []byte("k")
|
||||||
|
salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
||||||
|
_, err := bcrypt(key, 10, salt)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("One byte key resulted in error: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTooLongPasswordsWork(t *testing.T) {
|
||||||
|
salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
||||||
|
// One byte over the usual 56 byte limit that blowfish has
|
||||||
|
tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456")
|
||||||
|
tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C")
|
||||||
|
hash, err := bcrypt(tooLongPass, 10, salt)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bcrypt blew up on long password: %v", err)
|
||||||
|
}
|
||||||
|
if !bytes.HasSuffix(tooLongExpected, hash) {
|
||||||
|
t.Errorf("%v should be the suffix of %v", hash, tooLongExpected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type InvalidHashTest struct {
|
||||||
|
err error
|
||||||
|
hash []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
var invalidTests = []InvalidHashTest{
|
||||||
|
{ErrHashTooShort, []byte("$2a$10$fooo")},
|
||||||
|
{ErrHashTooShort, []byte("$2a")},
|
||||||
|
{HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
|
||||||
|
{InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
|
||||||
|
{InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInvalidHashErrors(t *testing.T) {
|
||||||
|
check := func(name string, expected, err error) {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("%s: Should have returned an error", name)
|
||||||
|
}
|
||||||
|
if err != nil && err != expected {
|
||||||
|
t.Errorf("%s gave err %v but should have given %v", name, err, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, iht := range invalidTests {
|
||||||
|
_, err := newFromHash(iht.hash)
|
||||||
|
check("newFromHash", iht.err, err)
|
||||||
|
err = CompareHashAndPassword(iht.hash, []byte("anything"))
|
||||||
|
check("CompareHashAndPassword", iht.err, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnpaddedBase64Encoding(t *testing.T) {
|
||||||
|
original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30}
|
||||||
|
encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
||||||
|
|
||||||
|
encoded := base64Encode(original)
|
||||||
|
|
||||||
|
if !bytes.Equal(encodedOriginal, encoded) {
|
||||||
|
t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal)
|
||||||
|
}
|
||||||
|
|
||||||
|
decoded, err := base64Decode(encodedOriginal)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("base64Decode blew up: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(decoded, original) {
|
||||||
|
t.Errorf("Decoded %v should have equaled %v", decoded, original)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCost(t *testing.T) {
|
||||||
|
suffix := "XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C"
|
||||||
|
for _, vers := range []string{"2a", "2"} {
|
||||||
|
for _, cost := range []int{4, 10} {
|
||||||
|
s := fmt.Sprintf("$%s$%02d$%s", vers, cost, suffix)
|
||||||
|
h := []byte(s)
|
||||||
|
actual, err := Cost(h)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Cost, error: %s", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if actual != cost {
|
||||||
|
t.Errorf("Cost, expected: %d, actual: %d", cost, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err := Cost([]byte("$a$a$" + suffix))
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Cost, malformed but no error returned")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCostValidationInHash(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pass := []byte("mypassword")
|
||||||
|
|
||||||
|
for c := 0; c < MinCost; c++ {
|
||||||
|
p, _ := newFromPassword(pass, c)
|
||||||
|
if p.cost != DefaultCost {
|
||||||
|
t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p, _ := newFromPassword(pass, 14)
|
||||||
|
if p.cost != 14 {
|
||||||
|
t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost)
|
||||||
|
}
|
||||||
|
|
||||||
|
hp, _ := newFromHash(p.Hash())
|
||||||
|
if p.cost != hp.cost {
|
||||||
|
t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := newFromPassword(pass, 32)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("newFromPassword: should return a cost error")
|
||||||
|
}
|
||||||
|
if err != InvalidCostError(32) {
|
||||||
|
t.Errorf("newFromPassword: should return cost error, got %#v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCostReturnsWithLeadingZeroes(t *testing.T) {
|
||||||
|
hp, _ := newFromPassword([]byte("abcdefgh"), 7)
|
||||||
|
cost := hp.Hash()[4:7]
|
||||||
|
expected := []byte("07$")
|
||||||
|
|
||||||
|
if !bytes.Equal(expected, cost) {
|
||||||
|
t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMinorNotRequired(t *testing.T) {
|
||||||
|
noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
|
||||||
|
h, err := newFromHash(noMinorHash)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("No minor hash blew up: %s", err)
|
||||||
|
}
|
||||||
|
if h.minor != 0 {
|
||||||
|
t.Errorf("Should leave minor version at 0, but was %d", h.minor)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(noMinorHash, h.Hash()) {
|
||||||
|
t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEqual(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
passwd := []byte("somepasswordyoulike")
|
||||||
|
hash, _ := GenerateFromPassword(passwd, 10)
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
CompareHashAndPassword(hash, passwd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkGeneration(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
passwd := []byte("mylongpassword1234")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
GenerateFromPassword(passwd, 10)
|
||||||
|
}
|
||||||
|
}
|
159
vendor/golang.org/x/crypto/blowfish/block.go
generated
vendored
Normal file
159
vendor/golang.org/x/crypto/blowfish/block.go
generated
vendored
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package blowfish
|
||||||
|
|
||||||
|
// getNextWord returns the next big-endian uint32 value from the byte slice
|
||||||
|
// at the given position in a circular manner, updating the position.
|
||||||
|
func getNextWord(b []byte, pos *int) uint32 {
|
||||||
|
var w uint32
|
||||||
|
j := *pos
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
w = w<<8 | uint32(b[j])
|
||||||
|
j++
|
||||||
|
if j >= len(b) {
|
||||||
|
j = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*pos = j
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
|
||||||
|
// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
|
||||||
|
// pi and substitution tables for calls to Encrypt. This is used, primarily,
|
||||||
|
// by the bcrypt package to reuse the Blowfish key schedule during its
|
||||||
|
// set up. It's unlikely that you need to use this directly.
|
||||||
|
func ExpandKey(key []byte, c *Cipher) {
|
||||||
|
j := 0
|
||||||
|
for i := 0; i < 18; i++ {
|
||||||
|
// Using inlined getNextWord for performance.
|
||||||
|
var d uint32
|
||||||
|
for k := 0; k < 4; k++ {
|
||||||
|
d = d<<8 | uint32(key[j])
|
||||||
|
j++
|
||||||
|
if j >= len(key) {
|
||||||
|
j = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.p[i] ^= d
|
||||||
|
}
|
||||||
|
|
||||||
|
var l, r uint32
|
||||||
|
for i := 0; i < 18; i += 2 {
|
||||||
|
l, r = encryptBlock(l, r, c)
|
||||||
|
c.p[i], c.p[i+1] = l, r
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 256; i += 2 {
|
||||||
|
l, r = encryptBlock(l, r, c)
|
||||||
|
c.s0[i], c.s0[i+1] = l, r
|
||||||
|
}
|
||||||
|
for i := 0; i < 256; i += 2 {
|
||||||
|
l, r = encryptBlock(l, r, c)
|
||||||
|
c.s1[i], c.s1[i+1] = l, r
|
||||||
|
}
|
||||||
|
for i := 0; i < 256; i += 2 {
|
||||||
|
l, r = encryptBlock(l, r, c)
|
||||||
|
c.s2[i], c.s2[i+1] = l, r
|
||||||
|
}
|
||||||
|
for i := 0; i < 256; i += 2 {
|
||||||
|
l, r = encryptBlock(l, r, c)
|
||||||
|
c.s3[i], c.s3[i+1] = l, r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is similar to ExpandKey, but folds the salt during the key
|
||||||
|
// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
|
||||||
|
// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
|
||||||
|
// and specializing it here is useful.
|
||||||
|
func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
|
||||||
|
j := 0
|
||||||
|
for i := 0; i < 18; i++ {
|
||||||
|
c.p[i] ^= getNextWord(key, &j)
|
||||||
|
}
|
||||||
|
|
||||||
|
j = 0
|
||||||
|
var l, r uint32
|
||||||
|
for i := 0; i < 18; i += 2 {
|
||||||
|
l ^= getNextWord(salt, &j)
|
||||||
|
r ^= getNextWord(salt, &j)
|
||||||
|
l, r = encryptBlock(l, r, c)
|
||||||
|
c.p[i], c.p[i+1] = l, r
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 256; i += 2 {
|
||||||
|
l ^= getNextWord(salt, &j)
|
||||||
|
r ^= getNextWord(salt, &j)
|
||||||
|
l, r = encryptBlock(l, r, c)
|
||||||
|
c.s0[i], c.s0[i+1] = l, r
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 256; i += 2 {
|
||||||
|
l ^= getNextWord(salt, &j)
|
||||||
|
r ^= getNextWord(salt, &j)
|
||||||
|
l, r = encryptBlock(l, r, c)
|
||||||
|
c.s1[i], c.s1[i+1] = l, r
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 256; i += 2 {
|
||||||
|
l ^= getNextWord(salt, &j)
|
||||||
|
r ^= getNextWord(salt, &j)
|
||||||
|
l, r = encryptBlock(l, r, c)
|
||||||
|
c.s2[i], c.s2[i+1] = l, r
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 256; i += 2 {
|
||||||
|
l ^= getNextWord(salt, &j)
|
||||||
|
r ^= getNextWord(salt, &j)
|
||||||
|
l, r = encryptBlock(l, r, c)
|
||||||
|
c.s3[i], c.s3[i+1] = l, r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
|
||||||
|
xl, xr := l, r
|
||||||
|
xl ^= c.p[0]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
|
||||||
|
xr ^= c.p[17]
|
||||||
|
return xr, xl
|
||||||
|
}
|
||||||
|
|
||||||
|
func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
|
||||||
|
xl, xr := l, r
|
||||||
|
xl ^= c.p[17]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
|
||||||
|
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
|
||||||
|
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
|
||||||
|
xr ^= c.p[0]
|
||||||
|
return xr, xl
|
||||||
|
}
|
274
vendor/golang.org/x/crypto/blowfish/blowfish_test.go
generated
vendored
Normal file
274
vendor/golang.org/x/crypto/blowfish/blowfish_test.go
generated
vendored
Normal file
|
@ -0,0 +1,274 @@
|
||||||
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package blowfish
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
type CryptTest struct {
|
||||||
|
key []byte
|
||||||
|
in []byte
|
||||||
|
out []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test vector values are from http://www.schneier.com/code/vectors.txt.
|
||||||
|
var encryptTests = []CryptTest{
|
||||||
|
{
|
||||||
|
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
[]byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
|
||||||
|
{
|
||||||
|
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||||
|
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||||
|
[]byte{0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}},
|
||||||
|
{
|
||||||
|
[]byte{0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
[]byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
|
||||||
|
[]byte{0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}},
|
||||||
|
{
|
||||||
|
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
||||||
|
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
||||||
|
[]byte{0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D}},
|
||||||
|
|
||||||
|
{
|
||||||
|
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
||||||
|
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
||||||
|
[]byte{0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96}},
|
||||||
|
{
|
||||||
|
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
||||||
|
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
||||||
|
[]byte{0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7}},
|
||||||
|
{
|
||||||
|
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
[]byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
|
||||||
|
{
|
||||||
|
[]byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
|
||||||
|
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
||||||
|
[]byte{0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D}},
|
||||||
|
{
|
||||||
|
[]byte{0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57},
|
||||||
|
[]byte{0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42},
|
||||||
|
[]byte{0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B}},
|
||||||
|
{
|
||||||
|
[]byte{0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E},
|
||||||
|
[]byte{0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA},
|
||||||
|
[]byte{0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0}},
|
||||||
|
{
|
||||||
|
[]byte{0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86},
|
||||||
|
[]byte{0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72},
|
||||||
|
[]byte{0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4}},
|
||||||
|
{
|
||||||
|
[]byte{0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E},
|
||||||
|
[]byte{0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A},
|
||||||
|
[]byte{0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB}},
|
||||||
|
{
|
||||||
|
[]byte{0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6},
|
||||||
|
[]byte{0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2},
|
||||||
|
[]byte{0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A}},
|
||||||
|
{
|
||||||
|
[]byte{0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE},
|
||||||
|
[]byte{0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A},
|
||||||
|
[]byte{0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18}},
|
||||||
|
{
|
||||||
|
[]byte{0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6},
|
||||||
|
[]byte{0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2},
|
||||||
|
[]byte{0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98}},
|
||||||
|
{
|
||||||
|
[]byte{0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE},
|
||||||
|
[]byte{0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A},
|
||||||
|
[]byte{0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5}},
|
||||||
|
{
|
||||||
|
[]byte{0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16},
|
||||||
|
[]byte{0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
|
||||||
|
[]byte{0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79}},
|
||||||
|
{
|
||||||
|
[]byte{0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F},
|
||||||
|
[]byte{0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A},
|
||||||
|
[]byte{0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3}},
|
||||||
|
{
|
||||||
|
[]byte{0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46},
|
||||||
|
[]byte{0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32},
|
||||||
|
[]byte{0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69}},
|
||||||
|
{
|
||||||
|
[]byte{0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E},
|
||||||
|
[]byte{0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA},
|
||||||
|
[]byte{0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B}},
|
||||||
|
{
|
||||||
|
[]byte{0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76},
|
||||||
|
[]byte{0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62},
|
||||||
|
[]byte{0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E}},
|
||||||
|
{
|
||||||
|
[]byte{0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07},
|
||||||
|
[]byte{0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2},
|
||||||
|
[]byte{0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD}},
|
||||||
|
{
|
||||||
|
[]byte{0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F},
|
||||||
|
[]byte{0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA},
|
||||||
|
[]byte{0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19}},
|
||||||
|
{
|
||||||
|
[]byte{0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7},
|
||||||
|
[]byte{0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92},
|
||||||
|
[]byte{0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3}},
|
||||||
|
{
|
||||||
|
[]byte{0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF},
|
||||||
|
[]byte{0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A},
|
||||||
|
[]byte{0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5}},
|
||||||
|
{
|
||||||
|
[]byte{0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6},
|
||||||
|
[]byte{0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2},
|
||||||
|
[]byte{0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78}},
|
||||||
|
{
|
||||||
|
[]byte{0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF},
|
||||||
|
[]byte{0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A},
|
||||||
|
[]byte{0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01}},
|
||||||
|
{
|
||||||
|
[]byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
|
||||||
|
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
||||||
|
[]byte{0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2}},
|
||||||
|
{
|
||||||
|
[]byte{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
|
||||||
|
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
||||||
|
[]byte{0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE}},
|
||||||
|
{
|
||||||
|
[]byte{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
|
||||||
|
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
||||||
|
[]byte{0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D}},
|
||||||
|
{
|
||||||
|
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||||
|
[]byte{0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4}},
|
||||||
|
{
|
||||||
|
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||||
|
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
[]byte{0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC}},
|
||||||
|
{
|
||||||
|
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
||||||
|
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
[]byte{0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A}},
|
||||||
|
{
|
||||||
|
[]byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
|
||||||
|
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||||
|
[]byte{0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A}},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCipherEncrypt(t *testing.T) {
|
||||||
|
for i, tt := range encryptTests {
|
||||||
|
c, err := NewCipher(tt.key)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ct := make([]byte, len(tt.out))
|
||||||
|
c.Encrypt(ct, tt.in)
|
||||||
|
for j, v := range ct {
|
||||||
|
if v != tt.out[j] {
|
||||||
|
t.Errorf("Cipher.Encrypt, test vector #%d: cipher-text[%d] = %#x, expected %#x", i, j, v, tt.out[j])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCipherDecrypt(t *testing.T) {
|
||||||
|
for i, tt := range encryptTests {
|
||||||
|
c, err := NewCipher(tt.key)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pt := make([]byte, len(tt.in))
|
||||||
|
c.Decrypt(pt, tt.out)
|
||||||
|
for j, v := range pt {
|
||||||
|
if v != tt.in[j] {
|
||||||
|
t.Errorf("Cipher.Decrypt, test vector #%d: plain-text[%d] = %#x, expected %#x", i, j, v, tt.in[j])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSaltedCipherKeyLength(t *testing.T) {
|
||||||
|
if _, err := NewSaltedCipher(nil, []byte{'a'}); err != KeySizeError(0) {
|
||||||
|
t.Errorf("NewSaltedCipher with short key, gave error %#v, expected %#v", err, KeySizeError(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
// A 57-byte key. One over the typical blowfish restriction.
|
||||||
|
key := []byte("012345678901234567890123456789012345678901234567890123456")
|
||||||
|
if _, err := NewSaltedCipher(key, []byte{'a'}); err != nil {
|
||||||
|
t.Errorf("NewSaltedCipher with long key, gave error %#v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test vectors generated with Blowfish from OpenSSH.
|
||||||
|
var saltedVectors = [][8]byte{
|
||||||
|
{0x0c, 0x82, 0x3b, 0x7b, 0x8d, 0x01, 0x4b, 0x7e},
|
||||||
|
{0xd1, 0xe1, 0x93, 0xf0, 0x70, 0xa6, 0xdb, 0x12},
|
||||||
|
{0xfc, 0x5e, 0xba, 0xde, 0xcb, 0xf8, 0x59, 0xad},
|
||||||
|
{0x8a, 0x0c, 0x76, 0xe7, 0xdd, 0x2c, 0xd3, 0xa8},
|
||||||
|
{0x2c, 0xcb, 0x7b, 0xee, 0xac, 0x7b, 0x7f, 0xf8},
|
||||||
|
{0xbb, 0xf6, 0x30, 0x6f, 0xe1, 0x5d, 0x62, 0xbf},
|
||||||
|
{0x97, 0x1e, 0xc1, 0x3d, 0x3d, 0xe0, 0x11, 0xe9},
|
||||||
|
{0x06, 0xd7, 0x4d, 0xb1, 0x80, 0xa3, 0xb1, 0x38},
|
||||||
|
{0x67, 0xa1, 0xa9, 0x75, 0x0e, 0x5b, 0xc6, 0xb4},
|
||||||
|
{0x51, 0x0f, 0x33, 0x0e, 0x4f, 0x67, 0xd2, 0x0c},
|
||||||
|
{0xf1, 0x73, 0x7e, 0xd8, 0x44, 0xea, 0xdb, 0xe5},
|
||||||
|
{0x14, 0x0e, 0x16, 0xce, 0x7f, 0x4a, 0x9c, 0x7b},
|
||||||
|
{0x4b, 0xfe, 0x43, 0xfd, 0xbf, 0x36, 0x04, 0x47},
|
||||||
|
{0xb1, 0xeb, 0x3e, 0x15, 0x36, 0xa7, 0xbb, 0xe2},
|
||||||
|
{0x6d, 0x0b, 0x41, 0xdd, 0x00, 0x98, 0x0b, 0x19},
|
||||||
|
{0xd3, 0xce, 0x45, 0xce, 0x1d, 0x56, 0xb7, 0xfc},
|
||||||
|
{0xd9, 0xf0, 0xfd, 0xda, 0xc0, 0x23, 0xb7, 0x93},
|
||||||
|
{0x4c, 0x6f, 0xa1, 0xe4, 0x0c, 0xa8, 0xca, 0x57},
|
||||||
|
{0xe6, 0x2f, 0x28, 0xa7, 0x0c, 0x94, 0x0d, 0x08},
|
||||||
|
{0x8f, 0xe3, 0xf0, 0xb6, 0x29, 0xe3, 0x44, 0x03},
|
||||||
|
{0xff, 0x98, 0xdd, 0x04, 0x45, 0xb4, 0x6d, 0x1f},
|
||||||
|
{0x9e, 0x45, 0x4d, 0x18, 0x40, 0x53, 0xdb, 0xef},
|
||||||
|
{0xb7, 0x3b, 0xef, 0x29, 0xbe, 0xa8, 0x13, 0x71},
|
||||||
|
{0x02, 0x54, 0x55, 0x41, 0x8e, 0x04, 0xfc, 0xad},
|
||||||
|
{0x6a, 0x0a, 0xee, 0x7c, 0x10, 0xd9, 0x19, 0xfe},
|
||||||
|
{0x0a, 0x22, 0xd9, 0x41, 0xcc, 0x23, 0x87, 0x13},
|
||||||
|
{0x6e, 0xff, 0x1f, 0xff, 0x36, 0x17, 0x9c, 0xbe},
|
||||||
|
{0x79, 0xad, 0xb7, 0x40, 0xf4, 0x9f, 0x51, 0xa6},
|
||||||
|
{0x97, 0x81, 0x99, 0xa4, 0xde, 0x9e, 0x9f, 0xb6},
|
||||||
|
{0x12, 0x19, 0x7a, 0x28, 0xd0, 0xdc, 0xcc, 0x92},
|
||||||
|
{0x81, 0xda, 0x60, 0x1e, 0x0e, 0xdd, 0x65, 0x56},
|
||||||
|
{0x7d, 0x76, 0x20, 0xb2, 0x73, 0xc9, 0x9e, 0xee},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSaltedCipher(t *testing.T) {
|
||||||
|
var key, salt [32]byte
|
||||||
|
for i := range key {
|
||||||
|
key[i] = byte(i)
|
||||||
|
salt[i] = byte(i + 32)
|
||||||
|
}
|
||||||
|
for i, v := range saltedVectors {
|
||||||
|
c, err := NewSaltedCipher(key[:], salt[:i])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var buf [8]byte
|
||||||
|
c.Encrypt(buf[:], buf[:])
|
||||||
|
if v != buf {
|
||||||
|
t.Errorf("%d: expected %x, got %x", i, v, buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkExpandKeyWithSalt(b *testing.B) {
|
||||||
|
key := make([]byte, 32)
|
||||||
|
salt := make([]byte, 16)
|
||||||
|
c, _ := NewCipher(key)
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
expandKeyWithSalt(key, salt, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkExpandKey(b *testing.B) {
|
||||||
|
key := make([]byte, 32)
|
||||||
|
c, _ := NewCipher(key)
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
ExpandKey(key, c)
|
||||||
|
}
|
||||||
|
}
|
91
vendor/golang.org/x/crypto/blowfish/cipher.go
generated
vendored
Normal file
91
vendor/golang.org/x/crypto/blowfish/cipher.go
generated
vendored
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
|
||||||
|
package blowfish // import "golang.org/x/crypto/blowfish"
|
||||||
|
|
||||||
|
// The code is a port of Bruce Schneier's C implementation.
|
||||||
|
// See http://www.schneier.com/blowfish.html.
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
// The Blowfish block size in bytes.
|
||||||
|
const BlockSize = 8
|
||||||
|
|
||||||
|
// A Cipher is an instance of Blowfish encryption using a particular key.
|
||||||
|
type Cipher struct {
|
||||||
|
p [18]uint32
|
||||||
|
s0, s1, s2, s3 [256]uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeySizeError int
|
||||||
|
|
||||||
|
func (k KeySizeError) Error() string {
|
||||||
|
return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCipher creates and returns a Cipher.
|
||||||
|
// The key argument should be the Blowfish key, from 1 to 56 bytes.
|
||||||
|
func NewCipher(key []byte) (*Cipher, error) {
|
||||||
|
var result Cipher
|
||||||
|
if k := len(key); k < 1 || k > 56 {
|
||||||
|
return nil, KeySizeError(k)
|
||||||
|
}
|
||||||
|
initCipher(&result)
|
||||||
|
ExpandKey(key, &result)
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
|
||||||
|
// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
|
||||||
|
// sufficient and desirable. For bcrypt compatiblity, the key can be over 56
|
||||||
|
// bytes.
|
||||||
|
func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
|
||||||
|
if len(salt) == 0 {
|
||||||
|
return NewCipher(key)
|
||||||
|
}
|
||||||
|
var result Cipher
|
||||||
|
if k := len(key); k < 1 {
|
||||||
|
return nil, KeySizeError(k)
|
||||||
|
}
|
||||||
|
initCipher(&result)
|
||||||
|
expandKeyWithSalt(key, salt, &result)
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockSize returns the Blowfish block size, 8 bytes.
|
||||||
|
// It is necessary to satisfy the Block interface in the
|
||||||
|
// package "crypto/cipher".
|
||||||
|
func (c *Cipher) BlockSize() int { return BlockSize }
|
||||||
|
|
||||||
|
// Encrypt encrypts the 8-byte buffer src using the key k
|
||||||
|
// and stores the result in dst.
|
||||||
|
// Note that for amounts of data larger than a block,
|
||||||
|
// it is not safe to just call Encrypt on successive blocks;
|
||||||
|
// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
|
||||||
|
func (c *Cipher) Encrypt(dst, src []byte) {
|
||||||
|
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
|
||||||
|
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
|
||||||
|
l, r = encryptBlock(l, r, c)
|
||||||
|
dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
|
||||||
|
dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt decrypts the 8-byte buffer src using the key k
|
||||||
|
// and stores the result in dst.
|
||||||
|
func (c *Cipher) Decrypt(dst, src []byte) {
|
||||||
|
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
|
||||||
|
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
|
||||||
|
l, r = decryptBlock(l, r, c)
|
||||||
|
dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
|
||||||
|
dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initCipher(c *Cipher) {
|
||||||
|
copy(c.p[0:], p[0:])
|
||||||
|
copy(c.s0[0:], s0[0:])
|
||||||
|
copy(c.s1[0:], s1[0:])
|
||||||
|
copy(c.s2[0:], s2[0:])
|
||||||
|
copy(c.s3[0:], s3[0:])
|
||||||
|
}
|
199
vendor/golang.org/x/crypto/blowfish/const.go
generated
vendored
Normal file
199
vendor/golang.org/x/crypto/blowfish/const.go
generated
vendored
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// The startup permutation array and substitution boxes.
|
||||||
|
// They are the hexadecimal digits of PI; see:
|
||||||
|
// http://www.schneier.com/code/constants.txt.
|
||||||
|
|
||||||
|
package blowfish
|
||||||
|
|
||||||
|
var s0 = [256]uint32{
|
||||||
|
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
|
||||||
|
0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
||||||
|
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
|
||||||
|
0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
||||||
|
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
|
||||||
|
0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
||||||
|
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
|
||||||
|
0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
||||||
|
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
|
||||||
|
0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
||||||
|
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
|
||||||
|
0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
||||||
|
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
|
||||||
|
0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
||||||
|
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
|
||||||
|
0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
||||||
|
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
|
||||||
|
0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
||||||
|
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
|
||||||
|
0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
||||||
|
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
|
||||||
|
0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
||||||
|
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
|
||||||
|
0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
||||||
|
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
|
||||||
|
0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
||||||
|
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
|
||||||
|
0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
||||||
|
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
|
||||||
|
0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
||||||
|
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
|
||||||
|
0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
||||||
|
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
|
||||||
|
0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
||||||
|
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
|
||||||
|
0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
||||||
|
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
|
||||||
|
0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
||||||
|
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
|
||||||
|
0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
||||||
|
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
|
||||||
|
0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
||||||
|
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
|
||||||
|
}
|
||||||
|
|
||||||
|
var s1 = [256]uint32{
|
||||||
|
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
|
||||||
|
0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
||||||
|
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
|
||||||
|
0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
||||||
|
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
|
||||||
|
0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
||||||
|
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
|
||||||
|
0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
||||||
|
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
|
||||||
|
0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
||||||
|
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
|
||||||
|
0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
||||||
|
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
|
||||||
|
0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
||||||
|
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
|
||||||
|
0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
||||||
|
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
|
||||||
|
0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
||||||
|
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
|
||||||
|
0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
||||||
|
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
|
||||||
|
0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
||||||
|
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
|
||||||
|
0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
||||||
|
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
|
||||||
|
0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
||||||
|
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
|
||||||
|
0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
||||||
|
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
|
||||||
|
0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
||||||
|
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
|
||||||
|
0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
||||||
|
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
|
||||||
|
0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
||||||
|
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
|
||||||
|
0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
||||||
|
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
|
||||||
|
0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
||||||
|
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
|
||||||
|
0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
||||||
|
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
|
||||||
|
0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
||||||
|
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
|
||||||
|
}
|
||||||
|
|
||||||
|
var s2 = [256]uint32{
|
||||||
|
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
|
||||||
|
0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
||||||
|
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
|
||||||
|
0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
||||||
|
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
|
||||||
|
0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
||||||
|
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
|
||||||
|
0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
||||||
|
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
|
||||||
|
0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
||||||
|
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
|
||||||
|
0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
||||||
|
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
|
||||||
|
0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
||||||
|
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
|
||||||
|
0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
||||||
|
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
|
||||||
|
0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
||||||
|
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
|
||||||
|
0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
||||||
|
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
|
||||||
|
0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
||||||
|
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
|
||||||
|
0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
||||||
|
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
|
||||||
|
0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
||||||
|
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
|
||||||
|
0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
||||||
|
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
|
||||||
|
0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
||||||
|
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
|
||||||
|
0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
||||||
|
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
|
||||||
|
0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
||||||
|
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
|
||||||
|
0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
||||||
|
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
|
||||||
|
0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
||||||
|
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
|
||||||
|
0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
||||||
|
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
|
||||||
|
0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
||||||
|
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
|
||||||
|
}
|
||||||
|
|
||||||
|
var s3 = [256]uint32{
|
||||||
|
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
|
||||||
|
0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
||||||
|
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
|
||||||
|
0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
||||||
|
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
|
||||||
|
0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
||||||
|
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
|
||||||
|
0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
||||||
|
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
|
||||||
|
0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
||||||
|
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
|
||||||
|
0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
||||||
|
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
|
||||||
|
0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
||||||
|
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
|
||||||
|
0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
||||||
|
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
|
||||||
|
0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
||||||
|
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
|
||||||
|
0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
||||||
|
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
|
||||||
|
0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
||||||
|
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
|
||||||
|
0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
||||||
|
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
|
||||||
|
0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
||||||
|
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
|
||||||
|
0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
||||||
|
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
|
||||||
|
0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
||||||
|
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
|
||||||
|
0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
||||||
|
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
|
||||||
|
0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
||||||
|
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
|
||||||
|
0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
||||||
|
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
|
||||||
|
0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
||||||
|
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
|
||||||
|
0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
||||||
|
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
|
||||||
|
0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
||||||
|
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
|
||||||
|
}
|
||||||
|
|
||||||
|
var p = [18]uint32{
|
||||||
|
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
|
||||||
|
0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
||||||
|
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
|
||||||
|
}
|
404
vendor/golang.org/x/crypto/bn256/bn256.go
generated
vendored
Normal file
404
vendor/golang.org/x/crypto/bn256/bn256.go
generated
vendored
Normal file
|
@ -0,0 +1,404 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package bn256 implements a particular bilinear group at the 128-bit security level.
|
||||||
|
//
|
||||||
|
// Bilinear groups are the basis of many of the new cryptographic protocols
|
||||||
|
// that have been proposed over the past decade. They consist of a triplet of
|
||||||
|
// groups (G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ
|
||||||
|
// (where gₓ is a generator of the respective group). That function is called
|
||||||
|
// a pairing function.
|
||||||
|
//
|
||||||
|
// This package specifically implements the Optimal Ate pairing over a 256-bit
|
||||||
|
// Barreto-Naehrig curve as described in
|
||||||
|
// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible
|
||||||
|
// with the implementation described in that paper.
|
||||||
|
package bn256 // import "golang.org/x/crypto/bn256"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"io"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BUG(agl): this implementation is not constant time.
|
||||||
|
// TODO(agl): keep GF(p²) elements in Mongomery form.
|
||||||
|
|
||||||
|
// G1 is an abstract cyclic group. The zero value is suitable for use as the
|
||||||
|
// output of an operation, but cannot be used as an input.
|
||||||
|
type G1 struct {
|
||||||
|
p *curvePoint
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomG1 returns x and g₁ˣ where x is a random, non-zero number read from r.
|
||||||
|
func RandomG1(r io.Reader) (*big.Int, *G1, error) {
|
||||||
|
var k *big.Int
|
||||||
|
var err error
|
||||||
|
|
||||||
|
for {
|
||||||
|
k, err = rand.Int(r, Order)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if k.Sign() > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return k, new(G1).ScalarBaseMult(k), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *G1) String() string {
|
||||||
|
return "bn256.G1" + g.p.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScalarBaseMult sets e to g*k where g is the generator of the group and
|
||||||
|
// then returns e.
|
||||||
|
func (e *G1) ScalarBaseMult(k *big.Int) *G1 {
|
||||||
|
if e.p == nil {
|
||||||
|
e.p = newCurvePoint(nil)
|
||||||
|
}
|
||||||
|
e.p.Mul(curveGen, k, new(bnPool))
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScalarMult sets e to a*k and then returns e.
|
||||||
|
func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 {
|
||||||
|
if e.p == nil {
|
||||||
|
e.p = newCurvePoint(nil)
|
||||||
|
}
|
||||||
|
e.p.Mul(a.p, k, new(bnPool))
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add sets e to a+b and then returns e.
|
||||||
|
// BUG(agl): this function is not complete: a==b fails.
|
||||||
|
func (e *G1) Add(a, b *G1) *G1 {
|
||||||
|
if e.p == nil {
|
||||||
|
e.p = newCurvePoint(nil)
|
||||||
|
}
|
||||||
|
e.p.Add(a.p, b.p, new(bnPool))
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neg sets e to -a and then returns e.
|
||||||
|
func (e *G1) Neg(a *G1) *G1 {
|
||||||
|
if e.p == nil {
|
||||||
|
e.p = newCurvePoint(nil)
|
||||||
|
}
|
||||||
|
e.p.Negative(a.p)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal converts n to a byte slice.
|
||||||
|
func (n *G1) Marshal() []byte {
|
||||||
|
n.p.MakeAffine(nil)
|
||||||
|
|
||||||
|
xBytes := new(big.Int).Mod(n.p.x, p).Bytes()
|
||||||
|
yBytes := new(big.Int).Mod(n.p.y, p).Bytes()
|
||||||
|
|
||||||
|
// Each value is a 256-bit number.
|
||||||
|
const numBytes = 256 / 8
|
||||||
|
|
||||||
|
ret := make([]byte, numBytes*2)
|
||||||
|
copy(ret[1*numBytes-len(xBytes):], xBytes)
|
||||||
|
copy(ret[2*numBytes-len(yBytes):], yBytes)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal sets e to the result of converting the output of Marshal back into
|
||||||
|
// a group element and then returns e.
|
||||||
|
func (e *G1) Unmarshal(m []byte) (*G1, bool) {
|
||||||
|
// Each value is a 256-bit number.
|
||||||
|
const numBytes = 256 / 8
|
||||||
|
|
||||||
|
if len(m) != 2*numBytes {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.p == nil {
|
||||||
|
e.p = newCurvePoint(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
e.p.x.SetBytes(m[0*numBytes : 1*numBytes])
|
||||||
|
e.p.y.SetBytes(m[1*numBytes : 2*numBytes])
|
||||||
|
|
||||||
|
if e.p.x.Sign() == 0 && e.p.y.Sign() == 0 {
|
||||||
|
// This is the point at infinity.
|
||||||
|
e.p.y.SetInt64(1)
|
||||||
|
e.p.z.SetInt64(0)
|
||||||
|
e.p.t.SetInt64(0)
|
||||||
|
} else {
|
||||||
|
e.p.z.SetInt64(1)
|
||||||
|
e.p.t.SetInt64(1)
|
||||||
|
|
||||||
|
if !e.p.IsOnCurve() {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return e, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// G2 is an abstract cyclic group. The zero value is suitable for use as the
|
||||||
|
// output of an operation, but cannot be used as an input.
|
||||||
|
type G2 struct {
|
||||||
|
p *twistPoint
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomG1 returns x and g₂ˣ where x is a random, non-zero number read from r.
|
||||||
|
func RandomG2(r io.Reader) (*big.Int, *G2, error) {
|
||||||
|
var k *big.Int
|
||||||
|
var err error
|
||||||
|
|
||||||
|
for {
|
||||||
|
k, err = rand.Int(r, Order)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if k.Sign() > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return k, new(G2).ScalarBaseMult(k), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *G2) String() string {
|
||||||
|
return "bn256.G2" + g.p.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScalarBaseMult sets e to g*k where g is the generator of the group and
|
||||||
|
// then returns out.
|
||||||
|
func (e *G2) ScalarBaseMult(k *big.Int) *G2 {
|
||||||
|
if e.p == nil {
|
||||||
|
e.p = newTwistPoint(nil)
|
||||||
|
}
|
||||||
|
e.p.Mul(twistGen, k, new(bnPool))
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScalarMult sets e to a*k and then returns e.
|
||||||
|
func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 {
|
||||||
|
if e.p == nil {
|
||||||
|
e.p = newTwistPoint(nil)
|
||||||
|
}
|
||||||
|
e.p.Mul(a.p, k, new(bnPool))
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add sets e to a+b and then returns e.
|
||||||
|
// BUG(agl): this function is not complete: a==b fails.
|
||||||
|
func (e *G2) Add(a, b *G2) *G2 {
|
||||||
|
if e.p == nil {
|
||||||
|
e.p = newTwistPoint(nil)
|
||||||
|
}
|
||||||
|
e.p.Add(a.p, b.p, new(bnPool))
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal converts n into a byte slice.
|
||||||
|
func (n *G2) Marshal() []byte {
|
||||||
|
n.p.MakeAffine(nil)
|
||||||
|
|
||||||
|
xxBytes := new(big.Int).Mod(n.p.x.x, p).Bytes()
|
||||||
|
xyBytes := new(big.Int).Mod(n.p.x.y, p).Bytes()
|
||||||
|
yxBytes := new(big.Int).Mod(n.p.y.x, p).Bytes()
|
||||||
|
yyBytes := new(big.Int).Mod(n.p.y.y, p).Bytes()
|
||||||
|
|
||||||
|
// Each value is a 256-bit number.
|
||||||
|
const numBytes = 256 / 8
|
||||||
|
|
||||||
|
ret := make([]byte, numBytes*4)
|
||||||
|
copy(ret[1*numBytes-len(xxBytes):], xxBytes)
|
||||||
|
copy(ret[2*numBytes-len(xyBytes):], xyBytes)
|
||||||
|
copy(ret[3*numBytes-len(yxBytes):], yxBytes)
|
||||||
|
copy(ret[4*numBytes-len(yyBytes):], yyBytes)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal sets e to the result of converting the output of Marshal back into
|
||||||
|
// a group element and then returns e.
|
||||||
|
func (e *G2) Unmarshal(m []byte) (*G2, bool) {
|
||||||
|
// Each value is a 256-bit number.
|
||||||
|
const numBytes = 256 / 8
|
||||||
|
|
||||||
|
if len(m) != 4*numBytes {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.p == nil {
|
||||||
|
e.p = newTwistPoint(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes])
|
||||||
|
e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes])
|
||||||
|
e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes])
|
||||||
|
e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes])
|
||||||
|
|
||||||
|
if e.p.x.x.Sign() == 0 &&
|
||||||
|
e.p.x.y.Sign() == 0 &&
|
||||||
|
e.p.y.x.Sign() == 0 &&
|
||||||
|
e.p.y.y.Sign() == 0 {
|
||||||
|
// This is the point at infinity.
|
||||||
|
e.p.y.SetOne()
|
||||||
|
e.p.z.SetZero()
|
||||||
|
e.p.t.SetZero()
|
||||||
|
} else {
|
||||||
|
e.p.z.SetOne()
|
||||||
|
e.p.t.SetOne()
|
||||||
|
|
||||||
|
if !e.p.IsOnCurve() {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return e, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// GT is an abstract cyclic group. The zero value is suitable for use as the
|
||||||
|
// output of an operation, but cannot be used as an input.
|
||||||
|
type GT struct {
|
||||||
|
p *gfP12
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GT) String() string {
|
||||||
|
return "bn256.GT" + g.p.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScalarMult sets e to a*k and then returns e.
|
||||||
|
func (e *GT) ScalarMult(a *GT, k *big.Int) *GT {
|
||||||
|
if e.p == nil {
|
||||||
|
e.p = newGFp12(nil)
|
||||||
|
}
|
||||||
|
e.p.Exp(a.p, k, new(bnPool))
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add sets e to a+b and then returns e.
|
||||||
|
func (e *GT) Add(a, b *GT) *GT {
|
||||||
|
if e.p == nil {
|
||||||
|
e.p = newGFp12(nil)
|
||||||
|
}
|
||||||
|
e.p.Mul(a.p, b.p, new(bnPool))
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neg sets e to -a and then returns e.
|
||||||
|
func (e *GT) Neg(a *GT) *GT {
|
||||||
|
if e.p == nil {
|
||||||
|
e.p = newGFp12(nil)
|
||||||
|
}
|
||||||
|
e.p.Invert(a.p, new(bnPool))
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal converts n into a byte slice.
|
||||||
|
func (n *GT) Marshal() []byte {
|
||||||
|
n.p.Minimal()
|
||||||
|
|
||||||
|
xxxBytes := n.p.x.x.x.Bytes()
|
||||||
|
xxyBytes := n.p.x.x.y.Bytes()
|
||||||
|
xyxBytes := n.p.x.y.x.Bytes()
|
||||||
|
xyyBytes := n.p.x.y.y.Bytes()
|
||||||
|
xzxBytes := n.p.x.z.x.Bytes()
|
||||||
|
xzyBytes := n.p.x.z.y.Bytes()
|
||||||
|
yxxBytes := n.p.y.x.x.Bytes()
|
||||||
|
yxyBytes := n.p.y.x.y.Bytes()
|
||||||
|
yyxBytes := n.p.y.y.x.Bytes()
|
||||||
|
yyyBytes := n.p.y.y.y.Bytes()
|
||||||
|
yzxBytes := n.p.y.z.x.Bytes()
|
||||||
|
yzyBytes := n.p.y.z.y.Bytes()
|
||||||
|
|
||||||
|
// Each value is a 256-bit number.
|
||||||
|
const numBytes = 256 / 8
|
||||||
|
|
||||||
|
ret := make([]byte, numBytes*12)
|
||||||
|
copy(ret[1*numBytes-len(xxxBytes):], xxxBytes)
|
||||||
|
copy(ret[2*numBytes-len(xxyBytes):], xxyBytes)
|
||||||
|
copy(ret[3*numBytes-len(xyxBytes):], xyxBytes)
|
||||||
|
copy(ret[4*numBytes-len(xyyBytes):], xyyBytes)
|
||||||
|
copy(ret[5*numBytes-len(xzxBytes):], xzxBytes)
|
||||||
|
copy(ret[6*numBytes-len(xzyBytes):], xzyBytes)
|
||||||
|
copy(ret[7*numBytes-len(yxxBytes):], yxxBytes)
|
||||||
|
copy(ret[8*numBytes-len(yxyBytes):], yxyBytes)
|
||||||
|
copy(ret[9*numBytes-len(yyxBytes):], yyxBytes)
|
||||||
|
copy(ret[10*numBytes-len(yyyBytes):], yyyBytes)
|
||||||
|
copy(ret[11*numBytes-len(yzxBytes):], yzxBytes)
|
||||||
|
copy(ret[12*numBytes-len(yzyBytes):], yzyBytes)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal sets e to the result of converting the output of Marshal back into
|
||||||
|
// a group element and then returns e.
|
||||||
|
func (e *GT) Unmarshal(m []byte) (*GT, bool) {
|
||||||
|
// Each value is a 256-bit number.
|
||||||
|
const numBytes = 256 / 8
|
||||||
|
|
||||||
|
if len(m) != 12*numBytes {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.p == nil {
|
||||||
|
e.p = newGFp12(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
e.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes])
|
||||||
|
e.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes])
|
||||||
|
e.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes])
|
||||||
|
e.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes])
|
||||||
|
e.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes])
|
||||||
|
e.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes])
|
||||||
|
e.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes])
|
||||||
|
e.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes])
|
||||||
|
e.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes])
|
||||||
|
e.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes])
|
||||||
|
e.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes])
|
||||||
|
e.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes])
|
||||||
|
|
||||||
|
return e, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pair calculates an Optimal Ate pairing.
|
||||||
|
func Pair(g1 *G1, g2 *G2) *GT {
|
||||||
|
return >{optimalAte(g2.p, g1.p, new(bnPool))}
|
||||||
|
}
|
||||||
|
|
||||||
|
// bnPool implements a tiny cache of *big.Int objects that's used to reduce the
|
||||||
|
// number of allocations made during processing.
|
||||||
|
type bnPool struct {
|
||||||
|
bns []*big.Int
|
||||||
|
count int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pool *bnPool) Get() *big.Int {
|
||||||
|
if pool == nil {
|
||||||
|
return new(big.Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
pool.count++
|
||||||
|
l := len(pool.bns)
|
||||||
|
if l == 0 {
|
||||||
|
return new(big.Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
bn := pool.bns[l-1]
|
||||||
|
pool.bns = pool.bns[:l-1]
|
||||||
|
return bn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pool *bnPool) Put(bn *big.Int) {
|
||||||
|
if pool == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pool.bns = append(pool.bns, bn)
|
||||||
|
pool.count--
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pool *bnPool) Count() int {
|
||||||
|
return pool.count
|
||||||
|
}
|
304
vendor/golang.org/x/crypto/bn256/bn256_test.go
generated
vendored
Normal file
304
vendor/golang.org/x/crypto/bn256/bn256_test.go
generated
vendored
Normal file
|
@ -0,0 +1,304 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bn256
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGFp2Invert(t *testing.T) {
|
||||||
|
pool := new(bnPool)
|
||||||
|
|
||||||
|
a := newGFp2(pool)
|
||||||
|
a.x.SetString("23423492374", 10)
|
||||||
|
a.y.SetString("12934872398472394827398470", 10)
|
||||||
|
|
||||||
|
inv := newGFp2(pool)
|
||||||
|
inv.Invert(a, pool)
|
||||||
|
|
||||||
|
b := newGFp2(pool).Mul(inv, a, pool)
|
||||||
|
if b.x.Int64() != 0 || b.y.Int64() != 1 {
|
||||||
|
t.Fatalf("bad result for a^-1*a: %s %s", b.x, b.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Put(pool)
|
||||||
|
b.Put(pool)
|
||||||
|
inv.Put(pool)
|
||||||
|
|
||||||
|
if c := pool.Count(); c > 0 {
|
||||||
|
t.Errorf("Pool count non-zero: %d\n", c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isZero(n *big.Int) bool {
|
||||||
|
return new(big.Int).Mod(n, p).Int64() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func isOne(n *big.Int) bool {
|
||||||
|
return new(big.Int).Mod(n, p).Int64() == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGFp6Invert(t *testing.T) {
|
||||||
|
pool := new(bnPool)
|
||||||
|
|
||||||
|
a := newGFp6(pool)
|
||||||
|
a.x.x.SetString("239487238491", 10)
|
||||||
|
a.x.y.SetString("2356249827341", 10)
|
||||||
|
a.y.x.SetString("082659782", 10)
|
||||||
|
a.y.y.SetString("182703523765", 10)
|
||||||
|
a.z.x.SetString("978236549263", 10)
|
||||||
|
a.z.y.SetString("64893242", 10)
|
||||||
|
|
||||||
|
inv := newGFp6(pool)
|
||||||
|
inv.Invert(a, pool)
|
||||||
|
|
||||||
|
b := newGFp6(pool).Mul(inv, a, pool)
|
||||||
|
if !isZero(b.x.x) ||
|
||||||
|
!isZero(b.x.y) ||
|
||||||
|
!isZero(b.y.x) ||
|
||||||
|
!isZero(b.y.y) ||
|
||||||
|
!isZero(b.z.x) ||
|
||||||
|
!isOne(b.z.y) {
|
||||||
|
t.Fatalf("bad result for a^-1*a: %s", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Put(pool)
|
||||||
|
b.Put(pool)
|
||||||
|
inv.Put(pool)
|
||||||
|
|
||||||
|
if c := pool.Count(); c > 0 {
|
||||||
|
t.Errorf("Pool count non-zero: %d\n", c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGFp12Invert(t *testing.T) {
|
||||||
|
pool := new(bnPool)
|
||||||
|
|
||||||
|
a := newGFp12(pool)
|
||||||
|
a.x.x.x.SetString("239846234862342323958623", 10)
|
||||||
|
a.x.x.y.SetString("2359862352529835623", 10)
|
||||||
|
a.x.y.x.SetString("928836523", 10)
|
||||||
|
a.x.y.y.SetString("9856234", 10)
|
||||||
|
a.x.z.x.SetString("235635286", 10)
|
||||||
|
a.x.z.y.SetString("5628392833", 10)
|
||||||
|
a.y.x.x.SetString("252936598265329856238956532167968", 10)
|
||||||
|
a.y.x.y.SetString("23596239865236954178968", 10)
|
||||||
|
a.y.y.x.SetString("95421692834", 10)
|
||||||
|
a.y.y.y.SetString("236548", 10)
|
||||||
|
a.y.z.x.SetString("924523", 10)
|
||||||
|
a.y.z.y.SetString("12954623", 10)
|
||||||
|
|
||||||
|
inv := newGFp12(pool)
|
||||||
|
inv.Invert(a, pool)
|
||||||
|
|
||||||
|
b := newGFp12(pool).Mul(inv, a, pool)
|
||||||
|
if !isZero(b.x.x.x) ||
|
||||||
|
!isZero(b.x.x.y) ||
|
||||||
|
!isZero(b.x.y.x) ||
|
||||||
|
!isZero(b.x.y.y) ||
|
||||||
|
!isZero(b.x.z.x) ||
|
||||||
|
!isZero(b.x.z.y) ||
|
||||||
|
!isZero(b.y.x.x) ||
|
||||||
|
!isZero(b.y.x.y) ||
|
||||||
|
!isZero(b.y.y.x) ||
|
||||||
|
!isZero(b.y.y.y) ||
|
||||||
|
!isZero(b.y.z.x) ||
|
||||||
|
!isOne(b.y.z.y) {
|
||||||
|
t.Fatalf("bad result for a^-1*a: %s", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Put(pool)
|
||||||
|
b.Put(pool)
|
||||||
|
inv.Put(pool)
|
||||||
|
|
||||||
|
if c := pool.Count(); c > 0 {
|
||||||
|
t.Errorf("Pool count non-zero: %d\n", c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCurveImpl(t *testing.T) {
|
||||||
|
pool := new(bnPool)
|
||||||
|
|
||||||
|
g := &curvePoint{
|
||||||
|
pool.Get().SetInt64(1),
|
||||||
|
pool.Get().SetInt64(-2),
|
||||||
|
pool.Get().SetInt64(1),
|
||||||
|
pool.Get().SetInt64(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
x := pool.Get().SetInt64(32498273234)
|
||||||
|
X := newCurvePoint(pool).Mul(g, x, pool)
|
||||||
|
|
||||||
|
y := pool.Get().SetInt64(98732423523)
|
||||||
|
Y := newCurvePoint(pool).Mul(g, y, pool)
|
||||||
|
|
||||||
|
s1 := newCurvePoint(pool).Mul(X, y, pool).MakeAffine(pool)
|
||||||
|
s2 := newCurvePoint(pool).Mul(Y, x, pool).MakeAffine(pool)
|
||||||
|
|
||||||
|
if s1.x.Cmp(s2.x) != 0 ||
|
||||||
|
s2.x.Cmp(s1.x) != 0 {
|
||||||
|
t.Errorf("DH points don't match: (%s, %s) (%s, %s)", s1.x, s1.y, s2.x, s2.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
pool.Put(x)
|
||||||
|
X.Put(pool)
|
||||||
|
pool.Put(y)
|
||||||
|
Y.Put(pool)
|
||||||
|
s1.Put(pool)
|
||||||
|
s2.Put(pool)
|
||||||
|
g.Put(pool)
|
||||||
|
|
||||||
|
if c := pool.Count(); c > 0 {
|
||||||
|
t.Errorf("Pool count non-zero: %d\n", c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrderG1(t *testing.T) {
|
||||||
|
g := new(G1).ScalarBaseMult(Order)
|
||||||
|
if !g.p.IsInfinity() {
|
||||||
|
t.Error("G1 has incorrect order")
|
||||||
|
}
|
||||||
|
|
||||||
|
one := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
|
||||||
|
g.Add(g, one)
|
||||||
|
g.p.MakeAffine(nil)
|
||||||
|
if g.p.x.Cmp(one.p.x) != 0 || g.p.y.Cmp(one.p.y) != 0 {
|
||||||
|
t.Errorf("1+0 != 1 in G1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrderG2(t *testing.T) {
|
||||||
|
g := new(G2).ScalarBaseMult(Order)
|
||||||
|
if !g.p.IsInfinity() {
|
||||||
|
t.Error("G2 has incorrect order")
|
||||||
|
}
|
||||||
|
|
||||||
|
one := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1))
|
||||||
|
g.Add(g, one)
|
||||||
|
g.p.MakeAffine(nil)
|
||||||
|
if g.p.x.x.Cmp(one.p.x.x) != 0 ||
|
||||||
|
g.p.x.y.Cmp(one.p.x.y) != 0 ||
|
||||||
|
g.p.y.x.Cmp(one.p.y.x) != 0 ||
|
||||||
|
g.p.y.y.Cmp(one.p.y.y) != 0 {
|
||||||
|
t.Errorf("1+0 != 1 in G2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrderGT(t *testing.T) {
|
||||||
|
gt := Pair(&G1{curveGen}, &G2{twistGen})
|
||||||
|
g := new(GT).ScalarMult(gt, Order)
|
||||||
|
if !g.p.IsOne() {
|
||||||
|
t.Error("GT has incorrect order")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBilinearity(t *testing.T) {
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
a, p1, _ := RandomG1(rand.Reader)
|
||||||
|
b, p2, _ := RandomG2(rand.Reader)
|
||||||
|
e1 := Pair(p1, p2)
|
||||||
|
|
||||||
|
e2 := Pair(&G1{curveGen}, &G2{twistGen})
|
||||||
|
e2.ScalarMult(e2, a)
|
||||||
|
e2.ScalarMult(e2, b)
|
||||||
|
|
||||||
|
minusE2 := new(GT).Neg(e2)
|
||||||
|
e1.Add(e1, minusE2)
|
||||||
|
|
||||||
|
if !e1.p.IsOne() {
|
||||||
|
t.Fatalf("bad pairing result: %s", e1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestG1Marshal(t *testing.T) {
|
||||||
|
g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
|
||||||
|
form := g.Marshal()
|
||||||
|
_, ok := new(G1).Unmarshal(form)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("failed to unmarshal")
|
||||||
|
}
|
||||||
|
|
||||||
|
g.ScalarBaseMult(Order)
|
||||||
|
form = g.Marshal()
|
||||||
|
g2, ok := new(G1).Unmarshal(form)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("failed to unmarshal ∞")
|
||||||
|
}
|
||||||
|
if !g2.p.IsInfinity() {
|
||||||
|
t.Fatalf("∞ unmarshaled incorrectly")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestG2Marshal(t *testing.T) {
|
||||||
|
g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1))
|
||||||
|
form := g.Marshal()
|
||||||
|
_, ok := new(G2).Unmarshal(form)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("failed to unmarshal")
|
||||||
|
}
|
||||||
|
|
||||||
|
g.ScalarBaseMult(Order)
|
||||||
|
form = g.Marshal()
|
||||||
|
g2, ok := new(G2).Unmarshal(form)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("failed to unmarshal ∞")
|
||||||
|
}
|
||||||
|
if !g2.p.IsInfinity() {
|
||||||
|
t.Fatalf("∞ unmarshaled incorrectly")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestG1Identity(t *testing.T) {
|
||||||
|
g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(0))
|
||||||
|
if !g.p.IsInfinity() {
|
||||||
|
t.Error("failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestG2Identity(t *testing.T) {
|
||||||
|
g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(0))
|
||||||
|
if !g.p.IsInfinity() {
|
||||||
|
t.Error("failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTripartiteDiffieHellman(t *testing.T) {
|
||||||
|
a, _ := rand.Int(rand.Reader, Order)
|
||||||
|
b, _ := rand.Int(rand.Reader, Order)
|
||||||
|
c, _ := rand.Int(rand.Reader, Order)
|
||||||
|
|
||||||
|
pa, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(a).Marshal())
|
||||||
|
qa, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(a).Marshal())
|
||||||
|
pb, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(b).Marshal())
|
||||||
|
qb, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(b).Marshal())
|
||||||
|
pc, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(c).Marshal())
|
||||||
|
qc, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(c).Marshal())
|
||||||
|
|
||||||
|
k1 := Pair(pb, qc)
|
||||||
|
k1.ScalarMult(k1, a)
|
||||||
|
k1Bytes := k1.Marshal()
|
||||||
|
|
||||||
|
k2 := Pair(pc, qa)
|
||||||
|
k2.ScalarMult(k2, b)
|
||||||
|
k2Bytes := k2.Marshal()
|
||||||
|
|
||||||
|
k3 := Pair(pa, qb)
|
||||||
|
k3.ScalarMult(k3, c)
|
||||||
|
k3Bytes := k3.Marshal()
|
||||||
|
|
||||||
|
if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) {
|
||||||
|
t.Errorf("keys didn't agree")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkPairing(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Pair(&G1{curveGen}, &G2{twistGen})
|
||||||
|
}
|
||||||
|
}
|
44
vendor/golang.org/x/crypto/bn256/constants.go
generated
vendored
Normal file
44
vendor/golang.org/x/crypto/bn256/constants.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bn256
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
func bigFromBase10(s string) *big.Int {
|
||||||
|
n, _ := new(big.Int).SetString(s, 10)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// u is the BN parameter that determines the prime: 1868033³.
|
||||||
|
var u = bigFromBase10("6518589491078791937")
|
||||||
|
|
||||||
|
// p is a prime over which we form a basic field: 36u⁴+36u³+24u³+6u+1.
|
||||||
|
var p = bigFromBase10("65000549695646603732796438742359905742825358107623003571877145026864184071783")
|
||||||
|
|
||||||
|
// Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u³+6u+1.
|
||||||
|
var Order = bigFromBase10("65000549695646603732796438742359905742570406053903786389881062969044166799969")
|
||||||
|
|
||||||
|
// xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+3.
|
||||||
|
var xiToPMinus1Over6 = &gfP2{bigFromBase10("8669379979083712429711189836753509758585994370025260553045152614783263110636"), bigFromBase10("19998038925833620163537568958541907098007303196759855091367510456613536016040")}
|
||||||
|
|
||||||
|
// xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+3.
|
||||||
|
var xiToPMinus1Over3 = &gfP2{bigFromBase10("26098034838977895781559542626833399156321265654106457577426020397262786167059"), bigFromBase10("15931493369629630809226283458085260090334794394361662678240713231519278691715")}
|
||||||
|
|
||||||
|
// xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+3.
|
||||||
|
var xiToPMinus1Over2 = &gfP2{bigFromBase10("50997318142241922852281555961173165965672272825141804376761836765206060036244"), bigFromBase10("38665955945962842195025998234511023902832543644254935982879660597356748036009")}
|
||||||
|
|
||||||
|
// xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+3.
|
||||||
|
var xiToPSquaredMinus1Over3 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437752")
|
||||||
|
|
||||||
|
// xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+3 (a cubic root of unity, mod p).
|
||||||
|
var xiTo2PSquaredMinus2Over3 = bigFromBase10("4985783334309134261147736404674766913742361673560802634030")
|
||||||
|
|
||||||
|
// xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+3 (a cubic root of -1, mod p).
|
||||||
|
var xiToPSquaredMinus1Over6 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437753")
|
||||||
|
|
||||||
|
// xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+3.
|
||||||
|
var xiTo2PMinus2Over3 = &gfP2{bigFromBase10("19885131339612776214803633203834694332692106372356013117629940868870585019582"), bigFromBase10("21645619881471562101905880913352894726728173167203616652430647841922248593627")}
|
278
vendor/golang.org/x/crypto/bn256/curve.go
generated
vendored
Normal file
278
vendor/golang.org/x/crypto/bn256/curve.go
generated
vendored
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bn256
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// curvePoint implements the elliptic curve y²=x³+3. Points are kept in
|
||||||
|
// Jacobian form and t=z² when valid. G₁ is the set of points of this curve on
|
||||||
|
// GF(p).
|
||||||
|
type curvePoint struct {
|
||||||
|
x, y, z, t *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
var curveB = new(big.Int).SetInt64(3)
|
||||||
|
|
||||||
|
// curveGen is the generator of G₁.
|
||||||
|
var curveGen = &curvePoint{
|
||||||
|
new(big.Int).SetInt64(1),
|
||||||
|
new(big.Int).SetInt64(-2),
|
||||||
|
new(big.Int).SetInt64(1),
|
||||||
|
new(big.Int).SetInt64(1),
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCurvePoint(pool *bnPool) *curvePoint {
|
||||||
|
return &curvePoint{
|
||||||
|
pool.Get(),
|
||||||
|
pool.Get(),
|
||||||
|
pool.Get(),
|
||||||
|
pool.Get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *curvePoint) String() string {
|
||||||
|
c.MakeAffine(new(bnPool))
|
||||||
|
return "(" + c.x.String() + ", " + c.y.String() + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *curvePoint) Put(pool *bnPool) {
|
||||||
|
pool.Put(c.x)
|
||||||
|
pool.Put(c.y)
|
||||||
|
pool.Put(c.z)
|
||||||
|
pool.Put(c.t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *curvePoint) Set(a *curvePoint) {
|
||||||
|
c.x.Set(a.x)
|
||||||
|
c.y.Set(a.y)
|
||||||
|
c.z.Set(a.z)
|
||||||
|
c.t.Set(a.t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsOnCurve returns true iff c is on the curve where c must be in affine form.
|
||||||
|
func (c *curvePoint) IsOnCurve() bool {
|
||||||
|
yy := new(big.Int).Mul(c.y, c.y)
|
||||||
|
xxx := new(big.Int).Mul(c.x, c.x)
|
||||||
|
xxx.Mul(xxx, c.x)
|
||||||
|
yy.Sub(yy, xxx)
|
||||||
|
yy.Sub(yy, curveB)
|
||||||
|
if yy.Sign() < 0 || yy.Cmp(p) >= 0 {
|
||||||
|
yy.Mod(yy, p)
|
||||||
|
}
|
||||||
|
return yy.Sign() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *curvePoint) SetInfinity() {
|
||||||
|
c.z.SetInt64(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *curvePoint) IsInfinity() bool {
|
||||||
|
return c.z.Sign() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) {
|
||||||
|
if a.IsInfinity() {
|
||||||
|
c.Set(b)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if b.IsInfinity() {
|
||||||
|
c.Set(a)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
|
||||||
|
|
||||||
|
// Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2]
|
||||||
|
// by [u1:s1:z1·z2] and [u2:s2:z1·z2]
|
||||||
|
// where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³
|
||||||
|
z1z1 := pool.Get().Mul(a.z, a.z)
|
||||||
|
z1z1.Mod(z1z1, p)
|
||||||
|
z2z2 := pool.Get().Mul(b.z, b.z)
|
||||||
|
z2z2.Mod(z2z2, p)
|
||||||
|
u1 := pool.Get().Mul(a.x, z2z2)
|
||||||
|
u1.Mod(u1, p)
|
||||||
|
u2 := pool.Get().Mul(b.x, z1z1)
|
||||||
|
u2.Mod(u2, p)
|
||||||
|
|
||||||
|
t := pool.Get().Mul(b.z, z2z2)
|
||||||
|
t.Mod(t, p)
|
||||||
|
s1 := pool.Get().Mul(a.y, t)
|
||||||
|
s1.Mod(s1, p)
|
||||||
|
|
||||||
|
t.Mul(a.z, z1z1)
|
||||||
|
t.Mod(t, p)
|
||||||
|
s2 := pool.Get().Mul(b.y, t)
|
||||||
|
s2.Mod(s2, p)
|
||||||
|
|
||||||
|
// Compute x = (2h)²(s²-u1-u2)
|
||||||
|
// where s = (s2-s1)/(u2-u1) is the slope of the line through
|
||||||
|
// (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below.
|
||||||
|
// This is also:
|
||||||
|
// 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1)
|
||||||
|
// = r² - j - 2v
|
||||||
|
// with the notations below.
|
||||||
|
h := pool.Get().Sub(u2, u1)
|
||||||
|
xEqual := h.Sign() == 0
|
||||||
|
|
||||||
|
t.Add(h, h)
|
||||||
|
// i = 4h²
|
||||||
|
i := pool.Get().Mul(t, t)
|
||||||
|
i.Mod(i, p)
|
||||||
|
// j = 4h³
|
||||||
|
j := pool.Get().Mul(h, i)
|
||||||
|
j.Mod(j, p)
|
||||||
|
|
||||||
|
t.Sub(s2, s1)
|
||||||
|
yEqual := t.Sign() == 0
|
||||||
|
if xEqual && yEqual {
|
||||||
|
c.Double(a, pool)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r := pool.Get().Add(t, t)
|
||||||
|
|
||||||
|
v := pool.Get().Mul(u1, i)
|
||||||
|
v.Mod(v, p)
|
||||||
|
|
||||||
|
// t4 = 4(s2-s1)²
|
||||||
|
t4 := pool.Get().Mul(r, r)
|
||||||
|
t4.Mod(t4, p)
|
||||||
|
t.Add(v, v)
|
||||||
|
t6 := pool.Get().Sub(t4, j)
|
||||||
|
c.x.Sub(t6, t)
|
||||||
|
|
||||||
|
// Set y = -(2h)³(s1 + s*(x/4h²-u1))
|
||||||
|
// This is also
|
||||||
|
// y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j
|
||||||
|
t.Sub(v, c.x) // t7
|
||||||
|
t4.Mul(s1, j) // t8
|
||||||
|
t4.Mod(t4, p)
|
||||||
|
t6.Add(t4, t4) // t9
|
||||||
|
t4.Mul(r, t) // t10
|
||||||
|
t4.Mod(t4, p)
|
||||||
|
c.y.Sub(t4, t6)
|
||||||
|
|
||||||
|
// Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2
|
||||||
|
t.Add(a.z, b.z) // t11
|
||||||
|
t4.Mul(t, t) // t12
|
||||||
|
t4.Mod(t4, p)
|
||||||
|
t.Sub(t4, z1z1) // t13
|
||||||
|
t4.Sub(t, z2z2) // t14
|
||||||
|
c.z.Mul(t4, h)
|
||||||
|
c.z.Mod(c.z, p)
|
||||||
|
|
||||||
|
pool.Put(z1z1)
|
||||||
|
pool.Put(z2z2)
|
||||||
|
pool.Put(u1)
|
||||||
|
pool.Put(u2)
|
||||||
|
pool.Put(t)
|
||||||
|
pool.Put(s1)
|
||||||
|
pool.Put(s2)
|
||||||
|
pool.Put(h)
|
||||||
|
pool.Put(i)
|
||||||
|
pool.Put(j)
|
||||||
|
pool.Put(r)
|
||||||
|
pool.Put(v)
|
||||||
|
pool.Put(t4)
|
||||||
|
pool.Put(t6)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *curvePoint) Double(a *curvePoint, pool *bnPool) {
|
||||||
|
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
|
||||||
|
A := pool.Get().Mul(a.x, a.x)
|
||||||
|
A.Mod(A, p)
|
||||||
|
B := pool.Get().Mul(a.y, a.y)
|
||||||
|
B.Mod(B, p)
|
||||||
|
C := pool.Get().Mul(B, B)
|
||||||
|
C.Mod(C, p)
|
||||||
|
|
||||||
|
t := pool.Get().Add(a.x, B)
|
||||||
|
t2 := pool.Get().Mul(t, t)
|
||||||
|
t2.Mod(t2, p)
|
||||||
|
t.Sub(t2, A)
|
||||||
|
t2.Sub(t, C)
|
||||||
|
d := pool.Get().Add(t2, t2)
|
||||||
|
t.Add(A, A)
|
||||||
|
e := pool.Get().Add(t, A)
|
||||||
|
f := pool.Get().Mul(e, e)
|
||||||
|
f.Mod(f, p)
|
||||||
|
|
||||||
|
t.Add(d, d)
|
||||||
|
c.x.Sub(f, t)
|
||||||
|
|
||||||
|
t.Add(C, C)
|
||||||
|
t2.Add(t, t)
|
||||||
|
t.Add(t2, t2)
|
||||||
|
c.y.Sub(d, c.x)
|
||||||
|
t2.Mul(e, c.y)
|
||||||
|
t2.Mod(t2, p)
|
||||||
|
c.y.Sub(t2, t)
|
||||||
|
|
||||||
|
t.Mul(a.y, a.z)
|
||||||
|
t.Mod(t, p)
|
||||||
|
c.z.Add(t, t)
|
||||||
|
|
||||||
|
pool.Put(A)
|
||||||
|
pool.Put(B)
|
||||||
|
pool.Put(C)
|
||||||
|
pool.Put(t)
|
||||||
|
pool.Put(t2)
|
||||||
|
pool.Put(d)
|
||||||
|
pool.Put(e)
|
||||||
|
pool.Put(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint {
|
||||||
|
sum := newCurvePoint(pool)
|
||||||
|
sum.SetInfinity()
|
||||||
|
t := newCurvePoint(pool)
|
||||||
|
|
||||||
|
for i := scalar.BitLen(); i >= 0; i-- {
|
||||||
|
t.Double(sum, pool)
|
||||||
|
if scalar.Bit(i) != 0 {
|
||||||
|
sum.Add(t, a, pool)
|
||||||
|
} else {
|
||||||
|
sum.Set(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Set(sum)
|
||||||
|
sum.Put(pool)
|
||||||
|
t.Put(pool)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint {
|
||||||
|
if words := c.z.Bits(); len(words) == 1 && words[0] == 1 {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
zInv := pool.Get().ModInverse(c.z, p)
|
||||||
|
t := pool.Get().Mul(c.y, zInv)
|
||||||
|
t.Mod(t, p)
|
||||||
|
zInv2 := pool.Get().Mul(zInv, zInv)
|
||||||
|
zInv2.Mod(zInv2, p)
|
||||||
|
c.y.Mul(t, zInv2)
|
||||||
|
c.y.Mod(c.y, p)
|
||||||
|
t.Mul(c.x, zInv2)
|
||||||
|
t.Mod(t, p)
|
||||||
|
c.x.Set(t)
|
||||||
|
c.z.SetInt64(1)
|
||||||
|
c.t.SetInt64(1)
|
||||||
|
|
||||||
|
pool.Put(zInv)
|
||||||
|
pool.Put(t)
|
||||||
|
pool.Put(zInv2)
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *curvePoint) Negative(a *curvePoint) {
|
||||||
|
c.x.Set(a.x)
|
||||||
|
c.y.Neg(a.y)
|
||||||
|
c.z.Set(a.z)
|
||||||
|
c.t.SetInt64(0)
|
||||||
|
}
|
43
vendor/golang.org/x/crypto/bn256/example_test.go
generated
vendored
Normal file
43
vendor/golang.org/x/crypto/bn256/example_test.go
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bn256
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExamplePair() {
|
||||||
|
// This implements the tripartite Diffie-Hellman algorithm from "A One
|
||||||
|
// Round Protocol for Tripartite Diffie-Hellman", A. Joux.
|
||||||
|
// http://www.springerlink.com/content/cddc57yyva0hburb/fulltext.pdf
|
||||||
|
|
||||||
|
// Each of three parties, a, b and c, generate a private value.
|
||||||
|
a, _ := rand.Int(rand.Reader, Order)
|
||||||
|
b, _ := rand.Int(rand.Reader, Order)
|
||||||
|
c, _ := rand.Int(rand.Reader, Order)
|
||||||
|
|
||||||
|
// Then each party calculates g₁ and g₂ times their private value.
|
||||||
|
pa := new(G1).ScalarBaseMult(a)
|
||||||
|
qa := new(G2).ScalarBaseMult(a)
|
||||||
|
|
||||||
|
pb := new(G1).ScalarBaseMult(b)
|
||||||
|
qb := new(G2).ScalarBaseMult(b)
|
||||||
|
|
||||||
|
pc := new(G1).ScalarBaseMult(c)
|
||||||
|
qc := new(G2).ScalarBaseMult(c)
|
||||||
|
|
||||||
|
// Now each party exchanges its public values with the other two and
|
||||||
|
// all parties can calculate the shared key.
|
||||||
|
k1 := Pair(pb, qc)
|
||||||
|
k1.ScalarMult(k1, a)
|
||||||
|
|
||||||
|
k2 := Pair(pc, qa)
|
||||||
|
k2.ScalarMult(k2, b)
|
||||||
|
|
||||||
|
k3 := Pair(pa, qb)
|
||||||
|
k3.ScalarMult(k3, c)
|
||||||
|
|
||||||
|
// k1, k2 and k3 will all be equal.
|
||||||
|
}
|
200
vendor/golang.org/x/crypto/bn256/gfp12.go
generated
vendored
Normal file
200
vendor/golang.org/x/crypto/bn256/gfp12.go
generated
vendored
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bn256
|
||||||
|
|
||||||
|
// For details of the algorithms used, see "Multiplication and Squaring on
|
||||||
|
// Pairing-Friendly Fields, Devegili et al.
|
||||||
|
// http://eprint.iacr.org/2006/471.pdf.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// gfP12 implements the field of size p¹² as a quadratic extension of gfP6
|
||||||
|
// where ω²=τ.
|
||||||
|
type gfP12 struct {
|
||||||
|
x, y *gfP6 // value is xω + y
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGFp12(pool *bnPool) *gfP12 {
|
||||||
|
return &gfP12{newGFp6(pool), newGFp6(pool)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) String() string {
|
||||||
|
return "(" + e.x.String() + "," + e.y.String() + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) Put(pool *bnPool) {
|
||||||
|
e.x.Put(pool)
|
||||||
|
e.y.Put(pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) Set(a *gfP12) *gfP12 {
|
||||||
|
e.x.Set(a.x)
|
||||||
|
e.y.Set(a.y)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) SetZero() *gfP12 {
|
||||||
|
e.x.SetZero()
|
||||||
|
e.y.SetZero()
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) SetOne() *gfP12 {
|
||||||
|
e.x.SetZero()
|
||||||
|
e.y.SetOne()
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) Minimal() {
|
||||||
|
e.x.Minimal()
|
||||||
|
e.y.Minimal()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) IsZero() bool {
|
||||||
|
e.Minimal()
|
||||||
|
return e.x.IsZero() && e.y.IsZero()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) IsOne() bool {
|
||||||
|
e.Minimal()
|
||||||
|
return e.x.IsZero() && e.y.IsOne()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) Conjugate(a *gfP12) *gfP12 {
|
||||||
|
e.x.Negative(a.x)
|
||||||
|
e.y.Set(a.y)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) Negative(a *gfP12) *gfP12 {
|
||||||
|
e.x.Negative(a.x)
|
||||||
|
e.y.Negative(a.y)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p
|
||||||
|
func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 {
|
||||||
|
e.x.Frobenius(a.x, pool)
|
||||||
|
e.y.Frobenius(a.y, pool)
|
||||||
|
e.x.MulScalar(e.x, xiToPMinus1Over6, pool)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p²
|
||||||
|
func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 {
|
||||||
|
e.x.FrobeniusP2(a.x)
|
||||||
|
e.x.MulGFP(e.x, xiToPSquaredMinus1Over6)
|
||||||
|
e.y.FrobeniusP2(a.y)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) Add(a, b *gfP12) *gfP12 {
|
||||||
|
e.x.Add(a.x, b.x)
|
||||||
|
e.y.Add(a.y, b.y)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) Sub(a, b *gfP12) *gfP12 {
|
||||||
|
e.x.Sub(a.x, b.x)
|
||||||
|
e.y.Sub(a.y, b.y)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 {
|
||||||
|
tx := newGFp6(pool)
|
||||||
|
tx.Mul(a.x, b.y, pool)
|
||||||
|
t := newGFp6(pool)
|
||||||
|
t.Mul(b.x, a.y, pool)
|
||||||
|
tx.Add(tx, t)
|
||||||
|
|
||||||
|
ty := newGFp6(pool)
|
||||||
|
ty.Mul(a.y, b.y, pool)
|
||||||
|
t.Mul(a.x, b.x, pool)
|
||||||
|
t.MulTau(t, pool)
|
||||||
|
e.y.Add(ty, t)
|
||||||
|
e.x.Set(tx)
|
||||||
|
|
||||||
|
tx.Put(pool)
|
||||||
|
ty.Put(pool)
|
||||||
|
t.Put(pool)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 {
|
||||||
|
e.x.Mul(e.x, b, pool)
|
||||||
|
e.y.Mul(e.y, b, pool)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 {
|
||||||
|
sum := newGFp12(pool)
|
||||||
|
sum.SetOne()
|
||||||
|
t := newGFp12(pool)
|
||||||
|
|
||||||
|
for i := power.BitLen() - 1; i >= 0; i-- {
|
||||||
|
t.Square(sum, pool)
|
||||||
|
if power.Bit(i) != 0 {
|
||||||
|
sum.Mul(t, a, pool)
|
||||||
|
} else {
|
||||||
|
sum.Set(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Set(sum)
|
||||||
|
|
||||||
|
sum.Put(pool)
|
||||||
|
t.Put(pool)
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 {
|
||||||
|
// Complex squaring algorithm
|
||||||
|
v0 := newGFp6(pool)
|
||||||
|
v0.Mul(a.x, a.y, pool)
|
||||||
|
|
||||||
|
t := newGFp6(pool)
|
||||||
|
t.MulTau(a.x, pool)
|
||||||
|
t.Add(a.y, t)
|
||||||
|
ty := newGFp6(pool)
|
||||||
|
ty.Add(a.x, a.y)
|
||||||
|
ty.Mul(ty, t, pool)
|
||||||
|
ty.Sub(ty, v0)
|
||||||
|
t.MulTau(v0, pool)
|
||||||
|
ty.Sub(ty, t)
|
||||||
|
|
||||||
|
e.y.Set(ty)
|
||||||
|
e.x.Double(v0)
|
||||||
|
|
||||||
|
v0.Put(pool)
|
||||||
|
t.Put(pool)
|
||||||
|
ty.Put(pool)
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 {
|
||||||
|
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
||||||
|
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
||||||
|
t1 := newGFp6(pool)
|
||||||
|
t2 := newGFp6(pool)
|
||||||
|
|
||||||
|
t1.Square(a.x, pool)
|
||||||
|
t2.Square(a.y, pool)
|
||||||
|
t1.MulTau(t1, pool)
|
||||||
|
t1.Sub(t2, t1)
|
||||||
|
t2.Invert(t1, pool)
|
||||||
|
|
||||||
|
e.x.Negative(a.x)
|
||||||
|
e.y.Set(a.y)
|
||||||
|
e.MulScalar(e, t2, pool)
|
||||||
|
|
||||||
|
t1.Put(pool)
|
||||||
|
t2.Put(pool)
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
219
vendor/golang.org/x/crypto/bn256/gfp2.go
generated
vendored
Normal file
219
vendor/golang.org/x/crypto/bn256/gfp2.go
generated
vendored
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bn256
|
||||||
|
|
||||||
|
// For details of the algorithms used, see "Multiplication and Squaring on
|
||||||
|
// Pairing-Friendly Fields, Devegili et al.
|
||||||
|
// http://eprint.iacr.org/2006/471.pdf.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// gfP2 implements a field of size p² as a quadratic extension of the base
|
||||||
|
// field where i²=-1.
|
||||||
|
type gfP2 struct {
|
||||||
|
x, y *big.Int // value is xi+y.
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGFp2(pool *bnPool) *gfP2 {
|
||||||
|
return &gfP2{pool.Get(), pool.Get()}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) String() string {
|
||||||
|
x := new(big.Int).Mod(e.x, p)
|
||||||
|
y := new(big.Int).Mod(e.y, p)
|
||||||
|
return "(" + x.String() + "," + y.String() + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) Put(pool *bnPool) {
|
||||||
|
pool.Put(e.x)
|
||||||
|
pool.Put(e.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) Set(a *gfP2) *gfP2 {
|
||||||
|
e.x.Set(a.x)
|
||||||
|
e.y.Set(a.y)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) SetZero() *gfP2 {
|
||||||
|
e.x.SetInt64(0)
|
||||||
|
e.y.SetInt64(0)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) SetOne() *gfP2 {
|
||||||
|
e.x.SetInt64(0)
|
||||||
|
e.y.SetInt64(1)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) Minimal() {
|
||||||
|
if e.x.Sign() < 0 || e.x.Cmp(p) >= 0 {
|
||||||
|
e.x.Mod(e.x, p)
|
||||||
|
}
|
||||||
|
if e.y.Sign() < 0 || e.y.Cmp(p) >= 0 {
|
||||||
|
e.y.Mod(e.y, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) IsZero() bool {
|
||||||
|
return e.x.Sign() == 0 && e.y.Sign() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) IsOne() bool {
|
||||||
|
if e.x.Sign() != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
words := e.y.Bits()
|
||||||
|
return len(words) == 1 && words[0] == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) Conjugate(a *gfP2) *gfP2 {
|
||||||
|
e.y.Set(a.y)
|
||||||
|
e.x.Neg(a.x)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) Negative(a *gfP2) *gfP2 {
|
||||||
|
e.x.Neg(a.x)
|
||||||
|
e.y.Neg(a.y)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) Add(a, b *gfP2) *gfP2 {
|
||||||
|
e.x.Add(a.x, b.x)
|
||||||
|
e.y.Add(a.y, b.y)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) Sub(a, b *gfP2) *gfP2 {
|
||||||
|
e.x.Sub(a.x, b.x)
|
||||||
|
e.y.Sub(a.y, b.y)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) Double(a *gfP2) *gfP2 {
|
||||||
|
e.x.Lsh(a.x, 1)
|
||||||
|
e.y.Lsh(a.y, 1)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 {
|
||||||
|
sum := newGFp2(pool)
|
||||||
|
sum.SetOne()
|
||||||
|
t := newGFp2(pool)
|
||||||
|
|
||||||
|
for i := power.BitLen() - 1; i >= 0; i-- {
|
||||||
|
t.Square(sum, pool)
|
||||||
|
if power.Bit(i) != 0 {
|
||||||
|
sum.Mul(t, a, pool)
|
||||||
|
} else {
|
||||||
|
sum.Set(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Set(sum)
|
||||||
|
|
||||||
|
sum.Put(pool)
|
||||||
|
t.Put(pool)
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// See "Multiplication and Squaring in Pairing-Friendly Fields",
|
||||||
|
// http://eprint.iacr.org/2006/471.pdf
|
||||||
|
func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 {
|
||||||
|
tx := pool.Get().Mul(a.x, b.y)
|
||||||
|
t := pool.Get().Mul(b.x, a.y)
|
||||||
|
tx.Add(tx, t)
|
||||||
|
tx.Mod(tx, p)
|
||||||
|
|
||||||
|
ty := pool.Get().Mul(a.y, b.y)
|
||||||
|
t.Mul(a.x, b.x)
|
||||||
|
ty.Sub(ty, t)
|
||||||
|
e.y.Mod(ty, p)
|
||||||
|
e.x.Set(tx)
|
||||||
|
|
||||||
|
pool.Put(tx)
|
||||||
|
pool.Put(ty)
|
||||||
|
pool.Put(t)
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 {
|
||||||
|
e.x.Mul(a.x, b)
|
||||||
|
e.y.Mul(a.y, b)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// MulXi sets e=ξa where ξ=i+3 and then returns e.
|
||||||
|
func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 {
|
||||||
|
// (xi+y)(i+3) = (3x+y)i+(3y-x)
|
||||||
|
tx := pool.Get().Lsh(a.x, 1)
|
||||||
|
tx.Add(tx, a.x)
|
||||||
|
tx.Add(tx, a.y)
|
||||||
|
|
||||||
|
ty := pool.Get().Lsh(a.y, 1)
|
||||||
|
ty.Add(ty, a.y)
|
||||||
|
ty.Sub(ty, a.x)
|
||||||
|
|
||||||
|
e.x.Set(tx)
|
||||||
|
e.y.Set(ty)
|
||||||
|
|
||||||
|
pool.Put(tx)
|
||||||
|
pool.Put(ty)
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 {
|
||||||
|
// Complex squaring algorithm:
|
||||||
|
// (xi+b)² = (x+y)(y-x) + 2*i*x*y
|
||||||
|
t1 := pool.Get().Sub(a.y, a.x)
|
||||||
|
t2 := pool.Get().Add(a.x, a.y)
|
||||||
|
ty := pool.Get().Mul(t1, t2)
|
||||||
|
ty.Mod(ty, p)
|
||||||
|
|
||||||
|
t1.Mul(a.x, a.y)
|
||||||
|
t1.Lsh(t1, 1)
|
||||||
|
|
||||||
|
e.x.Mod(t1, p)
|
||||||
|
e.y.Set(ty)
|
||||||
|
|
||||||
|
pool.Put(t1)
|
||||||
|
pool.Put(t2)
|
||||||
|
pool.Put(ty)
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 {
|
||||||
|
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
||||||
|
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
||||||
|
t := pool.Get()
|
||||||
|
t.Mul(a.y, a.y)
|
||||||
|
t2 := pool.Get()
|
||||||
|
t2.Mul(a.x, a.x)
|
||||||
|
t.Add(t, t2)
|
||||||
|
|
||||||
|
inv := pool.Get()
|
||||||
|
inv.ModInverse(t, p)
|
||||||
|
|
||||||
|
e.x.Neg(a.x)
|
||||||
|
e.x.Mul(e.x, inv)
|
||||||
|
e.x.Mod(e.x, p)
|
||||||
|
|
||||||
|
e.y.Mul(a.y, inv)
|
||||||
|
e.y.Mod(e.y, p)
|
||||||
|
|
||||||
|
pool.Put(t)
|
||||||
|
pool.Put(t2)
|
||||||
|
pool.Put(inv)
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
296
vendor/golang.org/x/crypto/bn256/gfp6.go
generated
vendored
Normal file
296
vendor/golang.org/x/crypto/bn256/gfp6.go
generated
vendored
Normal file
|
@ -0,0 +1,296 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bn256
|
||||||
|
|
||||||
|
// For details of the algorithms used, see "Multiplication and Squaring on
|
||||||
|
// Pairing-Friendly Fields, Devegili et al.
|
||||||
|
// http://eprint.iacr.org/2006/471.pdf.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ
|
||||||
|
// and ξ=i+3.
|
||||||
|
type gfP6 struct {
|
||||||
|
x, y, z *gfP2 // value is xτ² + yτ + z
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGFp6(pool *bnPool) *gfP6 {
|
||||||
|
return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) String() string {
|
||||||
|
return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) Put(pool *bnPool) {
|
||||||
|
e.x.Put(pool)
|
||||||
|
e.y.Put(pool)
|
||||||
|
e.z.Put(pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) Set(a *gfP6) *gfP6 {
|
||||||
|
e.x.Set(a.x)
|
||||||
|
e.y.Set(a.y)
|
||||||
|
e.z.Set(a.z)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) SetZero() *gfP6 {
|
||||||
|
e.x.SetZero()
|
||||||
|
e.y.SetZero()
|
||||||
|
e.z.SetZero()
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) SetOne() *gfP6 {
|
||||||
|
e.x.SetZero()
|
||||||
|
e.y.SetZero()
|
||||||
|
e.z.SetOne()
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) Minimal() {
|
||||||
|
e.x.Minimal()
|
||||||
|
e.y.Minimal()
|
||||||
|
e.z.Minimal()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) IsZero() bool {
|
||||||
|
return e.x.IsZero() && e.y.IsZero() && e.z.IsZero()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) IsOne() bool {
|
||||||
|
return e.x.IsZero() && e.y.IsZero() && e.z.IsOne()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) Negative(a *gfP6) *gfP6 {
|
||||||
|
e.x.Negative(a.x)
|
||||||
|
e.y.Negative(a.y)
|
||||||
|
e.z.Negative(a.z)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 {
|
||||||
|
e.x.Conjugate(a.x)
|
||||||
|
e.y.Conjugate(a.y)
|
||||||
|
e.z.Conjugate(a.z)
|
||||||
|
|
||||||
|
e.x.Mul(e.x, xiTo2PMinus2Over3, pool)
|
||||||
|
e.y.Mul(e.y, xiToPMinus1Over3, pool)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z
|
||||||
|
func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 {
|
||||||
|
// τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3)
|
||||||
|
e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3)
|
||||||
|
// τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3)
|
||||||
|
e.y.MulScalar(a.y, xiToPSquaredMinus1Over3)
|
||||||
|
e.z.Set(a.z)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) Add(a, b *gfP6) *gfP6 {
|
||||||
|
e.x.Add(a.x, b.x)
|
||||||
|
e.y.Add(a.y, b.y)
|
||||||
|
e.z.Add(a.z, b.z)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) Sub(a, b *gfP6) *gfP6 {
|
||||||
|
e.x.Sub(a.x, b.x)
|
||||||
|
e.y.Sub(a.y, b.y)
|
||||||
|
e.z.Sub(a.z, b.z)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) Double(a *gfP6) *gfP6 {
|
||||||
|
e.x.Double(a.x)
|
||||||
|
e.y.Double(a.y)
|
||||||
|
e.z.Double(a.z)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 {
|
||||||
|
// "Multiplication and Squaring on Pairing-Friendly Fields"
|
||||||
|
// Section 4, Karatsuba method.
|
||||||
|
// http://eprint.iacr.org/2006/471.pdf
|
||||||
|
|
||||||
|
v0 := newGFp2(pool)
|
||||||
|
v0.Mul(a.z, b.z, pool)
|
||||||
|
v1 := newGFp2(pool)
|
||||||
|
v1.Mul(a.y, b.y, pool)
|
||||||
|
v2 := newGFp2(pool)
|
||||||
|
v2.Mul(a.x, b.x, pool)
|
||||||
|
|
||||||
|
t0 := newGFp2(pool)
|
||||||
|
t0.Add(a.x, a.y)
|
||||||
|
t1 := newGFp2(pool)
|
||||||
|
t1.Add(b.x, b.y)
|
||||||
|
tz := newGFp2(pool)
|
||||||
|
tz.Mul(t0, t1, pool)
|
||||||
|
|
||||||
|
tz.Sub(tz, v1)
|
||||||
|
tz.Sub(tz, v2)
|
||||||
|
tz.MulXi(tz, pool)
|
||||||
|
tz.Add(tz, v0)
|
||||||
|
|
||||||
|
t0.Add(a.y, a.z)
|
||||||
|
t1.Add(b.y, b.z)
|
||||||
|
ty := newGFp2(pool)
|
||||||
|
ty.Mul(t0, t1, pool)
|
||||||
|
ty.Sub(ty, v0)
|
||||||
|
ty.Sub(ty, v1)
|
||||||
|
t0.MulXi(v2, pool)
|
||||||
|
ty.Add(ty, t0)
|
||||||
|
|
||||||
|
t0.Add(a.x, a.z)
|
||||||
|
t1.Add(b.x, b.z)
|
||||||
|
tx := newGFp2(pool)
|
||||||
|
tx.Mul(t0, t1, pool)
|
||||||
|
tx.Sub(tx, v0)
|
||||||
|
tx.Add(tx, v1)
|
||||||
|
tx.Sub(tx, v2)
|
||||||
|
|
||||||
|
e.x.Set(tx)
|
||||||
|
e.y.Set(ty)
|
||||||
|
e.z.Set(tz)
|
||||||
|
|
||||||
|
t0.Put(pool)
|
||||||
|
t1.Put(pool)
|
||||||
|
tx.Put(pool)
|
||||||
|
ty.Put(pool)
|
||||||
|
tz.Put(pool)
|
||||||
|
v0.Put(pool)
|
||||||
|
v1.Put(pool)
|
||||||
|
v2.Put(pool)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 {
|
||||||
|
e.x.Mul(a.x, b, pool)
|
||||||
|
e.y.Mul(a.y, b, pool)
|
||||||
|
e.z.Mul(a.z, b, pool)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 {
|
||||||
|
e.x.MulScalar(a.x, b)
|
||||||
|
e.y.MulScalar(a.y, b)
|
||||||
|
e.z.MulScalar(a.z, b)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ
|
||||||
|
func (e *gfP6) MulTau(a *gfP6, pool *bnPool) {
|
||||||
|
tz := newGFp2(pool)
|
||||||
|
tz.MulXi(a.x, pool)
|
||||||
|
ty := newGFp2(pool)
|
||||||
|
ty.Set(a.y)
|
||||||
|
e.y.Set(a.z)
|
||||||
|
e.x.Set(ty)
|
||||||
|
e.z.Set(tz)
|
||||||
|
tz.Put(pool)
|
||||||
|
ty.Put(pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 {
|
||||||
|
v0 := newGFp2(pool).Square(a.z, pool)
|
||||||
|
v1 := newGFp2(pool).Square(a.y, pool)
|
||||||
|
v2 := newGFp2(pool).Square(a.x, pool)
|
||||||
|
|
||||||
|
c0 := newGFp2(pool).Add(a.x, a.y)
|
||||||
|
c0.Square(c0, pool)
|
||||||
|
c0.Sub(c0, v1)
|
||||||
|
c0.Sub(c0, v2)
|
||||||
|
c0.MulXi(c0, pool)
|
||||||
|
c0.Add(c0, v0)
|
||||||
|
|
||||||
|
c1 := newGFp2(pool).Add(a.y, a.z)
|
||||||
|
c1.Square(c1, pool)
|
||||||
|
c1.Sub(c1, v0)
|
||||||
|
c1.Sub(c1, v1)
|
||||||
|
xiV2 := newGFp2(pool).MulXi(v2, pool)
|
||||||
|
c1.Add(c1, xiV2)
|
||||||
|
|
||||||
|
c2 := newGFp2(pool).Add(a.x, a.z)
|
||||||
|
c2.Square(c2, pool)
|
||||||
|
c2.Sub(c2, v0)
|
||||||
|
c2.Add(c2, v1)
|
||||||
|
c2.Sub(c2, v2)
|
||||||
|
|
||||||
|
e.x.Set(c2)
|
||||||
|
e.y.Set(c1)
|
||||||
|
e.z.Set(c0)
|
||||||
|
|
||||||
|
v0.Put(pool)
|
||||||
|
v1.Put(pool)
|
||||||
|
v2.Put(pool)
|
||||||
|
c0.Put(pool)
|
||||||
|
c1.Put(pool)
|
||||||
|
c2.Put(pool)
|
||||||
|
xiV2.Put(pool)
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 {
|
||||||
|
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
||||||
|
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
||||||
|
|
||||||
|
// Here we can give a short explanation of how it works: let j be a cubic root of
|
||||||
|
// unity in GF(p²) so that 1+j+j²=0.
|
||||||
|
// Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
|
||||||
|
// = (xτ² + yτ + z)(Cτ²+Bτ+A)
|
||||||
|
// = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm).
|
||||||
|
//
|
||||||
|
// On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
|
||||||
|
// = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy)
|
||||||
|
//
|
||||||
|
// So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz)
|
||||||
|
t1 := newGFp2(pool)
|
||||||
|
|
||||||
|
A := newGFp2(pool)
|
||||||
|
A.Square(a.z, pool)
|
||||||
|
t1.Mul(a.x, a.y, pool)
|
||||||
|
t1.MulXi(t1, pool)
|
||||||
|
A.Sub(A, t1)
|
||||||
|
|
||||||
|
B := newGFp2(pool)
|
||||||
|
B.Square(a.x, pool)
|
||||||
|
B.MulXi(B, pool)
|
||||||
|
t1.Mul(a.y, a.z, pool)
|
||||||
|
B.Sub(B, t1)
|
||||||
|
|
||||||
|
C := newGFp2(pool)
|
||||||
|
C.Square(a.y, pool)
|
||||||
|
t1.Mul(a.x, a.z, pool)
|
||||||
|
C.Sub(C, t1)
|
||||||
|
|
||||||
|
F := newGFp2(pool)
|
||||||
|
F.Mul(C, a.y, pool)
|
||||||
|
F.MulXi(F, pool)
|
||||||
|
t1.Mul(A, a.z, pool)
|
||||||
|
F.Add(F, t1)
|
||||||
|
t1.Mul(B, a.x, pool)
|
||||||
|
t1.MulXi(t1, pool)
|
||||||
|
F.Add(F, t1)
|
||||||
|
|
||||||
|
F.Invert(F, pool)
|
||||||
|
|
||||||
|
e.x.Mul(C, F, pool)
|
||||||
|
e.y.Mul(B, F, pool)
|
||||||
|
e.z.Mul(A, F, pool)
|
||||||
|
|
||||||
|
t1.Put(pool)
|
||||||
|
A.Put(pool)
|
||||||
|
B.Put(pool)
|
||||||
|
C.Put(pool)
|
||||||
|
F.Put(pool)
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
395
vendor/golang.org/x/crypto/bn256/optate.go
generated
vendored
Normal file
395
vendor/golang.org/x/crypto/bn256/optate.go
generated
vendored
Normal file
|
@ -0,0 +1,395 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bn256
|
||||||
|
|
||||||
|
func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
|
||||||
|
// See the mixed addition algorithm from "Faster Computation of the
|
||||||
|
// Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
|
||||||
|
|
||||||
|
B := newGFp2(pool).Mul(p.x, r.t, pool)
|
||||||
|
|
||||||
|
D := newGFp2(pool).Add(p.y, r.z)
|
||||||
|
D.Square(D, pool)
|
||||||
|
D.Sub(D, r2)
|
||||||
|
D.Sub(D, r.t)
|
||||||
|
D.Mul(D, r.t, pool)
|
||||||
|
|
||||||
|
H := newGFp2(pool).Sub(B, r.x)
|
||||||
|
I := newGFp2(pool).Square(H, pool)
|
||||||
|
|
||||||
|
E := newGFp2(pool).Add(I, I)
|
||||||
|
E.Add(E, E)
|
||||||
|
|
||||||
|
J := newGFp2(pool).Mul(H, E, pool)
|
||||||
|
|
||||||
|
L1 := newGFp2(pool).Sub(D, r.y)
|
||||||
|
L1.Sub(L1, r.y)
|
||||||
|
|
||||||
|
V := newGFp2(pool).Mul(r.x, E, pool)
|
||||||
|
|
||||||
|
rOut = newTwistPoint(pool)
|
||||||
|
rOut.x.Square(L1, pool)
|
||||||
|
rOut.x.Sub(rOut.x, J)
|
||||||
|
rOut.x.Sub(rOut.x, V)
|
||||||
|
rOut.x.Sub(rOut.x, V)
|
||||||
|
|
||||||
|
rOut.z.Add(r.z, H)
|
||||||
|
rOut.z.Square(rOut.z, pool)
|
||||||
|
rOut.z.Sub(rOut.z, r.t)
|
||||||
|
rOut.z.Sub(rOut.z, I)
|
||||||
|
|
||||||
|
t := newGFp2(pool).Sub(V, rOut.x)
|
||||||
|
t.Mul(t, L1, pool)
|
||||||
|
t2 := newGFp2(pool).Mul(r.y, J, pool)
|
||||||
|
t2.Add(t2, t2)
|
||||||
|
rOut.y.Sub(t, t2)
|
||||||
|
|
||||||
|
rOut.t.Square(rOut.z, pool)
|
||||||
|
|
||||||
|
t.Add(p.y, rOut.z)
|
||||||
|
t.Square(t, pool)
|
||||||
|
t.Sub(t, r2)
|
||||||
|
t.Sub(t, rOut.t)
|
||||||
|
|
||||||
|
t2.Mul(L1, p.x, pool)
|
||||||
|
t2.Add(t2, t2)
|
||||||
|
a = newGFp2(pool)
|
||||||
|
a.Sub(t2, t)
|
||||||
|
|
||||||
|
c = newGFp2(pool)
|
||||||
|
c.MulScalar(rOut.z, q.y)
|
||||||
|
c.Add(c, c)
|
||||||
|
|
||||||
|
b = newGFp2(pool)
|
||||||
|
b.SetZero()
|
||||||
|
b.Sub(b, L1)
|
||||||
|
b.MulScalar(b, q.x)
|
||||||
|
b.Add(b, b)
|
||||||
|
|
||||||
|
B.Put(pool)
|
||||||
|
D.Put(pool)
|
||||||
|
H.Put(pool)
|
||||||
|
I.Put(pool)
|
||||||
|
E.Put(pool)
|
||||||
|
J.Put(pool)
|
||||||
|
L1.Put(pool)
|
||||||
|
V.Put(pool)
|
||||||
|
t.Put(pool)
|
||||||
|
t2.Put(pool)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
|
||||||
|
// See the doubling algorithm for a=0 from "Faster Computation of the
|
||||||
|
// Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
|
||||||
|
|
||||||
|
A := newGFp2(pool).Square(r.x, pool)
|
||||||
|
B := newGFp2(pool).Square(r.y, pool)
|
||||||
|
C := newGFp2(pool).Square(B, pool)
|
||||||
|
|
||||||
|
D := newGFp2(pool).Add(r.x, B)
|
||||||
|
D.Square(D, pool)
|
||||||
|
D.Sub(D, A)
|
||||||
|
D.Sub(D, C)
|
||||||
|
D.Add(D, D)
|
||||||
|
|
||||||
|
E := newGFp2(pool).Add(A, A)
|
||||||
|
E.Add(E, A)
|
||||||
|
|
||||||
|
G := newGFp2(pool).Square(E, pool)
|
||||||
|
|
||||||
|
rOut = newTwistPoint(pool)
|
||||||
|
rOut.x.Sub(G, D)
|
||||||
|
rOut.x.Sub(rOut.x, D)
|
||||||
|
|
||||||
|
rOut.z.Add(r.y, r.z)
|
||||||
|
rOut.z.Square(rOut.z, pool)
|
||||||
|
rOut.z.Sub(rOut.z, B)
|
||||||
|
rOut.z.Sub(rOut.z, r.t)
|
||||||
|
|
||||||
|
rOut.y.Sub(D, rOut.x)
|
||||||
|
rOut.y.Mul(rOut.y, E, pool)
|
||||||
|
t := newGFp2(pool).Add(C, C)
|
||||||
|
t.Add(t, t)
|
||||||
|
t.Add(t, t)
|
||||||
|
rOut.y.Sub(rOut.y, t)
|
||||||
|
|
||||||
|
rOut.t.Square(rOut.z, pool)
|
||||||
|
|
||||||
|
t.Mul(E, r.t, pool)
|
||||||
|
t.Add(t, t)
|
||||||
|
b = newGFp2(pool)
|
||||||
|
b.SetZero()
|
||||||
|
b.Sub(b, t)
|
||||||
|
b.MulScalar(b, q.x)
|
||||||
|
|
||||||
|
a = newGFp2(pool)
|
||||||
|
a.Add(r.x, E)
|
||||||
|
a.Square(a, pool)
|
||||||
|
a.Sub(a, A)
|
||||||
|
a.Sub(a, G)
|
||||||
|
t.Add(B, B)
|
||||||
|
t.Add(t, t)
|
||||||
|
a.Sub(a, t)
|
||||||
|
|
||||||
|
c = newGFp2(pool)
|
||||||
|
c.Mul(rOut.z, r.t, pool)
|
||||||
|
c.Add(c, c)
|
||||||
|
c.MulScalar(c, q.y)
|
||||||
|
|
||||||
|
A.Put(pool)
|
||||||
|
B.Put(pool)
|
||||||
|
C.Put(pool)
|
||||||
|
D.Put(pool)
|
||||||
|
E.Put(pool)
|
||||||
|
G.Put(pool)
|
||||||
|
t.Put(pool)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) {
|
||||||
|
a2 := newGFp6(pool)
|
||||||
|
a2.x.SetZero()
|
||||||
|
a2.y.Set(a)
|
||||||
|
a2.z.Set(b)
|
||||||
|
a2.Mul(a2, ret.x, pool)
|
||||||
|
t3 := newGFp6(pool).MulScalar(ret.y, c, pool)
|
||||||
|
|
||||||
|
t := newGFp2(pool)
|
||||||
|
t.Add(b, c)
|
||||||
|
t2 := newGFp6(pool)
|
||||||
|
t2.x.SetZero()
|
||||||
|
t2.y.Set(a)
|
||||||
|
t2.z.Set(t)
|
||||||
|
ret.x.Add(ret.x, ret.y)
|
||||||
|
|
||||||
|
ret.y.Set(t3)
|
||||||
|
|
||||||
|
ret.x.Mul(ret.x, t2, pool)
|
||||||
|
ret.x.Sub(ret.x, a2)
|
||||||
|
ret.x.Sub(ret.x, ret.y)
|
||||||
|
a2.MulTau(a2, pool)
|
||||||
|
ret.y.Add(ret.y, a2)
|
||||||
|
|
||||||
|
a2.Put(pool)
|
||||||
|
t3.Put(pool)
|
||||||
|
t2.Put(pool)
|
||||||
|
t.Put(pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sixuPlus2NAF is 6u+2 in non-adjacent form.
|
||||||
|
var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 1}
|
||||||
|
|
||||||
|
// miller implements the Miller loop for calculating the Optimal Ate pairing.
|
||||||
|
// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf
|
||||||
|
func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 {
|
||||||
|
ret := newGFp12(pool)
|
||||||
|
ret.SetOne()
|
||||||
|
|
||||||
|
aAffine := newTwistPoint(pool)
|
||||||
|
aAffine.Set(q)
|
||||||
|
aAffine.MakeAffine(pool)
|
||||||
|
|
||||||
|
bAffine := newCurvePoint(pool)
|
||||||
|
bAffine.Set(p)
|
||||||
|
bAffine.MakeAffine(pool)
|
||||||
|
|
||||||
|
minusA := newTwistPoint(pool)
|
||||||
|
minusA.Negative(aAffine, pool)
|
||||||
|
|
||||||
|
r := newTwistPoint(pool)
|
||||||
|
r.Set(aAffine)
|
||||||
|
|
||||||
|
r2 := newGFp2(pool)
|
||||||
|
r2.Square(aAffine.y, pool)
|
||||||
|
|
||||||
|
for i := len(sixuPlus2NAF) - 1; i > 0; i-- {
|
||||||
|
a, b, c, newR := lineFunctionDouble(r, bAffine, pool)
|
||||||
|
if i != len(sixuPlus2NAF)-1 {
|
||||||
|
ret.Square(ret, pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
mulLine(ret, a, b, c, pool)
|
||||||
|
a.Put(pool)
|
||||||
|
b.Put(pool)
|
||||||
|
c.Put(pool)
|
||||||
|
r.Put(pool)
|
||||||
|
r = newR
|
||||||
|
|
||||||
|
switch sixuPlus2NAF[i-1] {
|
||||||
|
case 1:
|
||||||
|
a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool)
|
||||||
|
case -1:
|
||||||
|
a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool)
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
mulLine(ret, a, b, c, pool)
|
||||||
|
a.Put(pool)
|
||||||
|
b.Put(pool)
|
||||||
|
c.Put(pool)
|
||||||
|
r.Put(pool)
|
||||||
|
r = newR
|
||||||
|
}
|
||||||
|
|
||||||
|
// In order to calculate Q1 we have to convert q from the sextic twist
|
||||||
|
// to the full GF(p^12) group, apply the Frobenius there, and convert
|
||||||
|
// back.
|
||||||
|
//
|
||||||
|
// The twist isomorphism is (x', y') -> (xω², yω³). If we consider just
|
||||||
|
// x for a moment, then after applying the Frobenius, we have x̄ω^(2p)
|
||||||
|
// where x̄ is the conjugate of x. If we are going to apply the inverse
|
||||||
|
// isomorphism we need a value with a single coefficient of ω² so we
|
||||||
|
// rewrite this as x̄ω^(2p-2)ω². ξ⁶ = ω and, due to the construction of
|
||||||
|
// p, 2p-2 is a multiple of six. Therefore we can rewrite as
|
||||||
|
// x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the
|
||||||
|
// ω².
|
||||||
|
//
|
||||||
|
// A similar argument can be made for the y value.
|
||||||
|
|
||||||
|
q1 := newTwistPoint(pool)
|
||||||
|
q1.x.Conjugate(aAffine.x)
|
||||||
|
q1.x.Mul(q1.x, xiToPMinus1Over3, pool)
|
||||||
|
q1.y.Conjugate(aAffine.y)
|
||||||
|
q1.y.Mul(q1.y, xiToPMinus1Over2, pool)
|
||||||
|
q1.z.SetOne()
|
||||||
|
q1.t.SetOne()
|
||||||
|
|
||||||
|
// For Q2 we are applying the p² Frobenius. The two conjugations cancel
|
||||||
|
// out and we are left only with the factors from the isomorphism. In
|
||||||
|
// the case of x, we end up with a pure number which is why
|
||||||
|
// xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We
|
||||||
|
// ignore this to end up with -Q2.
|
||||||
|
|
||||||
|
minusQ2 := newTwistPoint(pool)
|
||||||
|
minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3)
|
||||||
|
minusQ2.y.Set(aAffine.y)
|
||||||
|
minusQ2.z.SetOne()
|
||||||
|
minusQ2.t.SetOne()
|
||||||
|
|
||||||
|
r2.Square(q1.y, pool)
|
||||||
|
a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool)
|
||||||
|
mulLine(ret, a, b, c, pool)
|
||||||
|
a.Put(pool)
|
||||||
|
b.Put(pool)
|
||||||
|
c.Put(pool)
|
||||||
|
r.Put(pool)
|
||||||
|
r = newR
|
||||||
|
|
||||||
|
r2.Square(minusQ2.y, pool)
|
||||||
|
a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool)
|
||||||
|
mulLine(ret, a, b, c, pool)
|
||||||
|
a.Put(pool)
|
||||||
|
b.Put(pool)
|
||||||
|
c.Put(pool)
|
||||||
|
r.Put(pool)
|
||||||
|
r = newR
|
||||||
|
|
||||||
|
aAffine.Put(pool)
|
||||||
|
bAffine.Put(pool)
|
||||||
|
minusA.Put(pool)
|
||||||
|
r.Put(pool)
|
||||||
|
r2.Put(pool)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// finalExponentiation computes the (p¹²-1)/Order-th power of an element of
|
||||||
|
// GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from
|
||||||
|
// http://cryptojedi.org/papers/dclxvi-20100714.pdf)
|
||||||
|
func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 {
|
||||||
|
t1 := newGFp12(pool)
|
||||||
|
|
||||||
|
// This is the p^6-Frobenius
|
||||||
|
t1.x.Negative(in.x)
|
||||||
|
t1.y.Set(in.y)
|
||||||
|
|
||||||
|
inv := newGFp12(pool)
|
||||||
|
inv.Invert(in, pool)
|
||||||
|
t1.Mul(t1, inv, pool)
|
||||||
|
|
||||||
|
t2 := newGFp12(pool).FrobeniusP2(t1, pool)
|
||||||
|
t1.Mul(t1, t2, pool)
|
||||||
|
|
||||||
|
fp := newGFp12(pool).Frobenius(t1, pool)
|
||||||
|
fp2 := newGFp12(pool).FrobeniusP2(t1, pool)
|
||||||
|
fp3 := newGFp12(pool).Frobenius(fp2, pool)
|
||||||
|
|
||||||
|
fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
|
||||||
|
fu.Exp(t1, u, pool)
|
||||||
|
fu2.Exp(fu, u, pool)
|
||||||
|
fu3.Exp(fu2, u, pool)
|
||||||
|
|
||||||
|
y3 := newGFp12(pool).Frobenius(fu, pool)
|
||||||
|
fu2p := newGFp12(pool).Frobenius(fu2, pool)
|
||||||
|
fu3p := newGFp12(pool).Frobenius(fu3, pool)
|
||||||
|
y2 := newGFp12(pool).FrobeniusP2(fu2, pool)
|
||||||
|
|
||||||
|
y0 := newGFp12(pool)
|
||||||
|
y0.Mul(fp, fp2, pool)
|
||||||
|
y0.Mul(y0, fp3, pool)
|
||||||
|
|
||||||
|
y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
|
||||||
|
y1.Conjugate(t1)
|
||||||
|
y5.Conjugate(fu2)
|
||||||
|
y3.Conjugate(y3)
|
||||||
|
y4.Mul(fu, fu2p, pool)
|
||||||
|
y4.Conjugate(y4)
|
||||||
|
|
||||||
|
y6 := newGFp12(pool)
|
||||||
|
y6.Mul(fu3, fu3p, pool)
|
||||||
|
y6.Conjugate(y6)
|
||||||
|
|
||||||
|
t0 := newGFp12(pool)
|
||||||
|
t0.Square(y6, pool)
|
||||||
|
t0.Mul(t0, y4, pool)
|
||||||
|
t0.Mul(t0, y5, pool)
|
||||||
|
t1.Mul(y3, y5, pool)
|
||||||
|
t1.Mul(t1, t0, pool)
|
||||||
|
t0.Mul(t0, y2, pool)
|
||||||
|
t1.Square(t1, pool)
|
||||||
|
t1.Mul(t1, t0, pool)
|
||||||
|
t1.Square(t1, pool)
|
||||||
|
t0.Mul(t1, y1, pool)
|
||||||
|
t1.Mul(t1, y0, pool)
|
||||||
|
t0.Square(t0, pool)
|
||||||
|
t0.Mul(t0, t1, pool)
|
||||||
|
|
||||||
|
inv.Put(pool)
|
||||||
|
t1.Put(pool)
|
||||||
|
t2.Put(pool)
|
||||||
|
fp.Put(pool)
|
||||||
|
fp2.Put(pool)
|
||||||
|
fp3.Put(pool)
|
||||||
|
fu.Put(pool)
|
||||||
|
fu2.Put(pool)
|
||||||
|
fu3.Put(pool)
|
||||||
|
fu2p.Put(pool)
|
||||||
|
fu3p.Put(pool)
|
||||||
|
y0.Put(pool)
|
||||||
|
y1.Put(pool)
|
||||||
|
y2.Put(pool)
|
||||||
|
y3.Put(pool)
|
||||||
|
y4.Put(pool)
|
||||||
|
y5.Put(pool)
|
||||||
|
y6.Put(pool)
|
||||||
|
|
||||||
|
return t0
|
||||||
|
}
|
||||||
|
|
||||||
|
func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 {
|
||||||
|
e := miller(a, b, pool)
|
||||||
|
ret := finalExponentiation(e, pool)
|
||||||
|
e.Put(pool)
|
||||||
|
|
||||||
|
if a.IsInfinity() || b.IsInfinity() {
|
||||||
|
ret.SetOne()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
249
vendor/golang.org/x/crypto/bn256/twist.go
generated
vendored
Normal file
249
vendor/golang.org/x/crypto/bn256/twist.go
generated
vendored
Normal file
|
@ -0,0 +1,249 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bn256
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are
|
||||||
|
// kept in Jacobian form and t=z² when valid. The group G₂ is the set of
|
||||||
|
// n-torsion points of this curve over GF(p²) (where n = Order)
|
||||||
|
type twistPoint struct {
|
||||||
|
x, y, z, t *gfP2
|
||||||
|
}
|
||||||
|
|
||||||
|
var twistB = &gfP2{
|
||||||
|
bigFromBase10("6500054969564660373279643874235990574282535810762300357187714502686418407178"),
|
||||||
|
bigFromBase10("45500384786952622612957507119651934019977750675336102500314001518804928850249"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// twistGen is the generator of group G₂.
|
||||||
|
var twistGen = &twistPoint{
|
||||||
|
&gfP2{
|
||||||
|
bigFromBase10("21167961636542580255011770066570541300993051739349375019639421053990175267184"),
|
||||||
|
bigFromBase10("64746500191241794695844075326670126197795977525365406531717464316923369116492"),
|
||||||
|
},
|
||||||
|
&gfP2{
|
||||||
|
bigFromBase10("20666913350058776956210519119118544732556678129809273996262322366050359951122"),
|
||||||
|
bigFromBase10("17778617556404439934652658462602675281523610326338642107814333856843981424549"),
|
||||||
|
},
|
||||||
|
&gfP2{
|
||||||
|
bigFromBase10("0"),
|
||||||
|
bigFromBase10("1"),
|
||||||
|
},
|
||||||
|
&gfP2{
|
||||||
|
bigFromBase10("0"),
|
||||||
|
bigFromBase10("1"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTwistPoint(pool *bnPool) *twistPoint {
|
||||||
|
return &twistPoint{
|
||||||
|
newGFp2(pool),
|
||||||
|
newGFp2(pool),
|
||||||
|
newGFp2(pool),
|
||||||
|
newGFp2(pool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *twistPoint) String() string {
|
||||||
|
return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *twistPoint) Put(pool *bnPool) {
|
||||||
|
c.x.Put(pool)
|
||||||
|
c.y.Put(pool)
|
||||||
|
c.z.Put(pool)
|
||||||
|
c.t.Put(pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *twistPoint) Set(a *twistPoint) {
|
||||||
|
c.x.Set(a.x)
|
||||||
|
c.y.Set(a.y)
|
||||||
|
c.z.Set(a.z)
|
||||||
|
c.t.Set(a.t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsOnCurve returns true iff c is on the curve where c must be in affine form.
|
||||||
|
func (c *twistPoint) IsOnCurve() bool {
|
||||||
|
pool := new(bnPool)
|
||||||
|
yy := newGFp2(pool).Square(c.y, pool)
|
||||||
|
xxx := newGFp2(pool).Square(c.x, pool)
|
||||||
|
xxx.Mul(xxx, c.x, pool)
|
||||||
|
yy.Sub(yy, xxx)
|
||||||
|
yy.Sub(yy, twistB)
|
||||||
|
yy.Minimal()
|
||||||
|
return yy.x.Sign() == 0 && yy.y.Sign() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *twistPoint) SetInfinity() {
|
||||||
|
c.z.SetZero()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *twistPoint) IsInfinity() bool {
|
||||||
|
return c.z.IsZero()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) {
|
||||||
|
// For additional comments, see the same function in curve.go.
|
||||||
|
|
||||||
|
if a.IsInfinity() {
|
||||||
|
c.Set(b)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if b.IsInfinity() {
|
||||||
|
c.Set(a)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
|
||||||
|
z1z1 := newGFp2(pool).Square(a.z, pool)
|
||||||
|
z2z2 := newGFp2(pool).Square(b.z, pool)
|
||||||
|
u1 := newGFp2(pool).Mul(a.x, z2z2, pool)
|
||||||
|
u2 := newGFp2(pool).Mul(b.x, z1z1, pool)
|
||||||
|
|
||||||
|
t := newGFp2(pool).Mul(b.z, z2z2, pool)
|
||||||
|
s1 := newGFp2(pool).Mul(a.y, t, pool)
|
||||||
|
|
||||||
|
t.Mul(a.z, z1z1, pool)
|
||||||
|
s2 := newGFp2(pool).Mul(b.y, t, pool)
|
||||||
|
|
||||||
|
h := newGFp2(pool).Sub(u2, u1)
|
||||||
|
xEqual := h.IsZero()
|
||||||
|
|
||||||
|
t.Add(h, h)
|
||||||
|
i := newGFp2(pool).Square(t, pool)
|
||||||
|
j := newGFp2(pool).Mul(h, i, pool)
|
||||||
|
|
||||||
|
t.Sub(s2, s1)
|
||||||
|
yEqual := t.IsZero()
|
||||||
|
if xEqual && yEqual {
|
||||||
|
c.Double(a, pool)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r := newGFp2(pool).Add(t, t)
|
||||||
|
|
||||||
|
v := newGFp2(pool).Mul(u1, i, pool)
|
||||||
|
|
||||||
|
t4 := newGFp2(pool).Square(r, pool)
|
||||||
|
t.Add(v, v)
|
||||||
|
t6 := newGFp2(pool).Sub(t4, j)
|
||||||
|
c.x.Sub(t6, t)
|
||||||
|
|
||||||
|
t.Sub(v, c.x) // t7
|
||||||
|
t4.Mul(s1, j, pool) // t8
|
||||||
|
t6.Add(t4, t4) // t9
|
||||||
|
t4.Mul(r, t, pool) // t10
|
||||||
|
c.y.Sub(t4, t6)
|
||||||
|
|
||||||
|
t.Add(a.z, b.z) // t11
|
||||||
|
t4.Square(t, pool) // t12
|
||||||
|
t.Sub(t4, z1z1) // t13
|
||||||
|
t4.Sub(t, z2z2) // t14
|
||||||
|
c.z.Mul(t4, h, pool)
|
||||||
|
|
||||||
|
z1z1.Put(pool)
|
||||||
|
z2z2.Put(pool)
|
||||||
|
u1.Put(pool)
|
||||||
|
u2.Put(pool)
|
||||||
|
t.Put(pool)
|
||||||
|
s1.Put(pool)
|
||||||
|
s2.Put(pool)
|
||||||
|
h.Put(pool)
|
||||||
|
i.Put(pool)
|
||||||
|
j.Put(pool)
|
||||||
|
r.Put(pool)
|
||||||
|
v.Put(pool)
|
||||||
|
t4.Put(pool)
|
||||||
|
t6.Put(pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *twistPoint) Double(a *twistPoint, pool *bnPool) {
|
||||||
|
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
|
||||||
|
A := newGFp2(pool).Square(a.x, pool)
|
||||||
|
B := newGFp2(pool).Square(a.y, pool)
|
||||||
|
C := newGFp2(pool).Square(B, pool)
|
||||||
|
|
||||||
|
t := newGFp2(pool).Add(a.x, B)
|
||||||
|
t2 := newGFp2(pool).Square(t, pool)
|
||||||
|
t.Sub(t2, A)
|
||||||
|
t2.Sub(t, C)
|
||||||
|
d := newGFp2(pool).Add(t2, t2)
|
||||||
|
t.Add(A, A)
|
||||||
|
e := newGFp2(pool).Add(t, A)
|
||||||
|
f := newGFp2(pool).Square(e, pool)
|
||||||
|
|
||||||
|
t.Add(d, d)
|
||||||
|
c.x.Sub(f, t)
|
||||||
|
|
||||||
|
t.Add(C, C)
|
||||||
|
t2.Add(t, t)
|
||||||
|
t.Add(t2, t2)
|
||||||
|
c.y.Sub(d, c.x)
|
||||||
|
t2.Mul(e, c.y, pool)
|
||||||
|
c.y.Sub(t2, t)
|
||||||
|
|
||||||
|
t.Mul(a.y, a.z, pool)
|
||||||
|
c.z.Add(t, t)
|
||||||
|
|
||||||
|
A.Put(pool)
|
||||||
|
B.Put(pool)
|
||||||
|
C.Put(pool)
|
||||||
|
t.Put(pool)
|
||||||
|
t2.Put(pool)
|
||||||
|
d.Put(pool)
|
||||||
|
e.Put(pool)
|
||||||
|
f.Put(pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint {
|
||||||
|
sum := newTwistPoint(pool)
|
||||||
|
sum.SetInfinity()
|
||||||
|
t := newTwistPoint(pool)
|
||||||
|
|
||||||
|
for i := scalar.BitLen(); i >= 0; i-- {
|
||||||
|
t.Double(sum, pool)
|
||||||
|
if scalar.Bit(i) != 0 {
|
||||||
|
sum.Add(t, a, pool)
|
||||||
|
} else {
|
||||||
|
sum.Set(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Set(sum)
|
||||||
|
sum.Put(pool)
|
||||||
|
t.Put(pool)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint {
|
||||||
|
if c.z.IsOne() {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
zInv := newGFp2(pool).Invert(c.z, pool)
|
||||||
|
t := newGFp2(pool).Mul(c.y, zInv, pool)
|
||||||
|
zInv2 := newGFp2(pool).Square(zInv, pool)
|
||||||
|
c.y.Mul(t, zInv2, pool)
|
||||||
|
t.Mul(c.x, zInv2, pool)
|
||||||
|
c.x.Set(t)
|
||||||
|
c.z.SetOne()
|
||||||
|
c.t.SetOne()
|
||||||
|
|
||||||
|
zInv.Put(pool)
|
||||||
|
t.Put(pool)
|
||||||
|
zInv2.Put(pool)
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) {
|
||||||
|
c.x.Set(a.x)
|
||||||
|
c.y.SetZero()
|
||||||
|
c.y.Sub(c.y, a.y)
|
||||||
|
c.z.Set(a.z)
|
||||||
|
c.t.SetZero()
|
||||||
|
}
|
526
vendor/golang.org/x/crypto/cast5/cast5.go
generated
vendored
Normal file
526
vendor/golang.org/x/crypto/cast5/cast5.go
generated
vendored
Normal file
|
@ -0,0 +1,526 @@
|
||||||
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
|
||||||
|
// OpenPGP cipher.
|
||||||
|
package cast5 // import "golang.org/x/crypto/cast5"
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
const BlockSize = 8
|
||||||
|
const KeySize = 16
|
||||||
|
|
||||||
|
type Cipher struct {
|
||||||
|
masking [16]uint32
|
||||||
|
rotate [16]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCipher(key []byte) (c *Cipher, err error) {
|
||||||
|
if len(key) != KeySize {
|
||||||
|
return nil, errors.New("CAST5: keys must be 16 bytes")
|
||||||
|
}
|
||||||
|
|
||||||
|
c = new(Cipher)
|
||||||
|
c.keySchedule(key)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cipher) BlockSize() int {
|
||||||
|
return BlockSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cipher) Encrypt(dst, src []byte) {
|
||||||
|
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
|
||||||
|
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
|
||||||
|
|
||||||
|
l, r = r, l^f1(r, c.masking[0], c.rotate[0])
|
||||||
|
l, r = r, l^f2(r, c.masking[1], c.rotate[1])
|
||||||
|
l, r = r, l^f3(r, c.masking[2], c.rotate[2])
|
||||||
|
l, r = r, l^f1(r, c.masking[3], c.rotate[3])
|
||||||
|
|
||||||
|
l, r = r, l^f2(r, c.masking[4], c.rotate[4])
|
||||||
|
l, r = r, l^f3(r, c.masking[5], c.rotate[5])
|
||||||
|
l, r = r, l^f1(r, c.masking[6], c.rotate[6])
|
||||||
|
l, r = r, l^f2(r, c.masking[7], c.rotate[7])
|
||||||
|
|
||||||
|
l, r = r, l^f3(r, c.masking[8], c.rotate[8])
|
||||||
|
l, r = r, l^f1(r, c.masking[9], c.rotate[9])
|
||||||
|
l, r = r, l^f2(r, c.masking[10], c.rotate[10])
|
||||||
|
l, r = r, l^f3(r, c.masking[11], c.rotate[11])
|
||||||
|
|
||||||
|
l, r = r, l^f1(r, c.masking[12], c.rotate[12])
|
||||||
|
l, r = r, l^f2(r, c.masking[13], c.rotate[13])
|
||||||
|
l, r = r, l^f3(r, c.masking[14], c.rotate[14])
|
||||||
|
l, r = r, l^f1(r, c.masking[15], c.rotate[15])
|
||||||
|
|
||||||
|
dst[0] = uint8(r >> 24)
|
||||||
|
dst[1] = uint8(r >> 16)
|
||||||
|
dst[2] = uint8(r >> 8)
|
||||||
|
dst[3] = uint8(r)
|
||||||
|
dst[4] = uint8(l >> 24)
|
||||||
|
dst[5] = uint8(l >> 16)
|
||||||
|
dst[6] = uint8(l >> 8)
|
||||||
|
dst[7] = uint8(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cipher) Decrypt(dst, src []byte) {
|
||||||
|
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
|
||||||
|
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
|
||||||
|
|
||||||
|
l, r = r, l^f1(r, c.masking[15], c.rotate[15])
|
||||||
|
l, r = r, l^f3(r, c.masking[14], c.rotate[14])
|
||||||
|
l, r = r, l^f2(r, c.masking[13], c.rotate[13])
|
||||||
|
l, r = r, l^f1(r, c.masking[12], c.rotate[12])
|
||||||
|
|
||||||
|
l, r = r, l^f3(r, c.masking[11], c.rotate[11])
|
||||||
|
l, r = r, l^f2(r, c.masking[10], c.rotate[10])
|
||||||
|
l, r = r, l^f1(r, c.masking[9], c.rotate[9])
|
||||||
|
l, r = r, l^f3(r, c.masking[8], c.rotate[8])
|
||||||
|
|
||||||
|
l, r = r, l^f2(r, c.masking[7], c.rotate[7])
|
||||||
|
l, r = r, l^f1(r, c.masking[6], c.rotate[6])
|
||||||
|
l, r = r, l^f3(r, c.masking[5], c.rotate[5])
|
||||||
|
l, r = r, l^f2(r, c.masking[4], c.rotate[4])
|
||||||
|
|
||||||
|
l, r = r, l^f1(r, c.masking[3], c.rotate[3])
|
||||||
|
l, r = r, l^f3(r, c.masking[2], c.rotate[2])
|
||||||
|
l, r = r, l^f2(r, c.masking[1], c.rotate[1])
|
||||||
|
l, r = r, l^f1(r, c.masking[0], c.rotate[0])
|
||||||
|
|
||||||
|
dst[0] = uint8(r >> 24)
|
||||||
|
dst[1] = uint8(r >> 16)
|
||||||
|
dst[2] = uint8(r >> 8)
|
||||||
|
dst[3] = uint8(r)
|
||||||
|
dst[4] = uint8(l >> 24)
|
||||||
|
dst[5] = uint8(l >> 16)
|
||||||
|
dst[6] = uint8(l >> 8)
|
||||||
|
dst[7] = uint8(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
type keyScheduleA [4][7]uint8
|
||||||
|
type keyScheduleB [4][5]uint8
|
||||||
|
|
||||||
|
// keyScheduleRound contains the magic values for a round of the key schedule.
|
||||||
|
// The keyScheduleA deals with the lines like:
|
||||||
|
// z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8]
|
||||||
|
// Conceptually, both x and z are in the same array, x first. The first
|
||||||
|
// element describes which word of this array gets written to and the
|
||||||
|
// second, which word gets read. So, for the line above, it's "4, 0", because
|
||||||
|
// it's writing to the first word of z, which, being after x, is word 4, and
|
||||||
|
// reading from the first word of x: word 0.
|
||||||
|
//
|
||||||
|
// Next are the indexes into the S-boxes. Now the array is treated as bytes. So
|
||||||
|
// "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear
|
||||||
|
// that it's z that we're indexing.
|
||||||
|
//
|
||||||
|
// keyScheduleB deals with lines like:
|
||||||
|
// K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2]
|
||||||
|
// "K1" is ignored because key words are always written in order. So the five
|
||||||
|
// elements are the S-box indexes. They use the same form as in keyScheduleA,
|
||||||
|
// above.
|
||||||
|
|
||||||
|
type keyScheduleRound struct{}
|
||||||
|
type keySchedule []keyScheduleRound
|
||||||
|
|
||||||
|
var schedule = []struct {
|
||||||
|
a keyScheduleA
|
||||||
|
b keyScheduleB
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
keyScheduleA{
|
||||||
|
{4, 0, 0xd, 0xf, 0xc, 0xe, 0x8},
|
||||||
|
{5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
|
||||||
|
{6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
|
||||||
|
{7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
|
||||||
|
},
|
||||||
|
keyScheduleB{
|
||||||
|
{16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2},
|
||||||
|
{16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6},
|
||||||
|
{16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9},
|
||||||
|
{16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyScheduleA{
|
||||||
|
{0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
|
||||||
|
{1, 4, 0, 2, 1, 3, 16 + 2},
|
||||||
|
{2, 5, 7, 6, 5, 4, 16 + 1},
|
||||||
|
{3, 7, 0xa, 9, 0xb, 8, 16 + 3},
|
||||||
|
},
|
||||||
|
keyScheduleB{
|
||||||
|
{3, 2, 0xc, 0xd, 8},
|
||||||
|
{1, 0, 0xe, 0xf, 0xd},
|
||||||
|
{7, 6, 8, 9, 3},
|
||||||
|
{5, 4, 0xa, 0xb, 7},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyScheduleA{
|
||||||
|
{4, 0, 0xd, 0xf, 0xc, 0xe, 8},
|
||||||
|
{5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
|
||||||
|
{6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
|
||||||
|
{7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
|
||||||
|
},
|
||||||
|
keyScheduleB{
|
||||||
|
{16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9},
|
||||||
|
{16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc},
|
||||||
|
{16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2},
|
||||||
|
{16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyScheduleA{
|
||||||
|
{0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
|
||||||
|
{1, 4, 0, 2, 1, 3, 16 + 2},
|
||||||
|
{2, 5, 7, 6, 5, 4, 16 + 1},
|
||||||
|
{3, 7, 0xa, 9, 0xb, 8, 16 + 3},
|
||||||
|
},
|
||||||
|
keyScheduleB{
|
||||||
|
{8, 9, 7, 6, 3},
|
||||||
|
{0xa, 0xb, 5, 4, 7},
|
||||||
|
{0xc, 0xd, 3, 2, 8},
|
||||||
|
{0xe, 0xf, 1, 0, 0xd},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cipher) keySchedule(in []byte) {
|
||||||
|
var t [8]uint32
|
||||||
|
var k [32]uint32
|
||||||
|
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
j := i * 4
|
||||||
|
t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3])
|
||||||
|
}
|
||||||
|
|
||||||
|
x := []byte{6, 7, 4, 5}
|
||||||
|
ki := 0
|
||||||
|
|
||||||
|
for half := 0; half < 2; half++ {
|
||||||
|
for _, round := range schedule {
|
||||||
|
for j := 0; j < 4; j++ {
|
||||||
|
var a [7]uint8
|
||||||
|
copy(a[:], round.a[j][:])
|
||||||
|
w := t[a[1]]
|
||||||
|
w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff]
|
||||||
|
w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff]
|
||||||
|
w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff]
|
||||||
|
w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff]
|
||||||
|
w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff]
|
||||||
|
t[a[0]] = w
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := 0; j < 4; j++ {
|
||||||
|
var b [5]uint8
|
||||||
|
copy(b[:], round.b[j][:])
|
||||||
|
w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff]
|
||||||
|
w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff]
|
||||||
|
w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff]
|
||||||
|
w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff]
|
||||||
|
w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff]
|
||||||
|
k[ki] = w
|
||||||
|
ki++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 16; i++ {
|
||||||
|
c.masking[i] = k[i]
|
||||||
|
c.rotate[i] = uint8(k[16+i] & 0x1f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are the three 'f' functions. See RFC 2144, section 2.2.
|
||||||
|
func f1(d, m uint32, r uint8) uint32 {
|
||||||
|
t := m + d
|
||||||
|
I := (t << r) | (t >> (32 - r))
|
||||||
|
return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff]
|
||||||
|
}
|
||||||
|
|
||||||
|
func f2(d, m uint32, r uint8) uint32 {
|
||||||
|
t := m ^ d
|
||||||
|
I := (t << r) | (t >> (32 - r))
|
||||||
|
return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff]
|
||||||
|
}
|
||||||
|
|
||||||
|
func f3(d, m uint32, r uint8) uint32 {
|
||||||
|
t := m - d
|
||||||
|
I := (t << r) | (t >> (32 - r))
|
||||||
|
return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff]
|
||||||
|
}
|
||||||
|
|
||||||
|
var sBox = [8][256]uint32{
|
||||||
|
{
|
||||||
|
0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
|
||||||
|
0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
|
||||||
|
0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
|
||||||
|
0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
|
||||||
|
0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
|
||||||
|
0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
|
||||||
|
0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
|
||||||
|
0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
|
||||||
|
0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
|
||||||
|
0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
|
||||||
|
0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
|
||||||
|
0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
|
||||||
|
0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
|
||||||
|
0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
|
||||||
|
0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
|
||||||
|
0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
|
||||||
|
0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
|
||||||
|
0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
|
||||||
|
0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
|
||||||
|
0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
|
||||||
|
0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
|
||||||
|
0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
|
||||||
|
0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
|
||||||
|
0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
|
||||||
|
0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
|
||||||
|
0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
|
||||||
|
0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
|
||||||
|
0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
|
||||||
|
0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
|
||||||
|
0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
|
||||||
|
0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
|
||||||
|
0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
|
||||||
|
0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
|
||||||
|
0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
|
||||||
|
0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
|
||||||
|
0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
|
||||||
|
0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
|
||||||
|
0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
|
||||||
|
0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
|
||||||
|
0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
|
||||||
|
0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
|
||||||
|
0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
|
||||||
|
0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
|
||||||
|
0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
|
||||||
|
0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
|
||||||
|
0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
|
||||||
|
0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
|
||||||
|
0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
|
||||||
|
0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
|
||||||
|
0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
|
||||||
|
0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
|
||||||
|
0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
|
||||||
|
0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
|
||||||
|
0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
|
||||||
|
0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
|
||||||
|
0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
|
||||||
|
0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
|
||||||
|
0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
|
||||||
|
0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
|
||||||
|
0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
|
||||||
|
0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
|
||||||
|
0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
|
||||||
|
0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
|
||||||
|
0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
|
||||||
|
0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
|
||||||
|
0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
|
||||||
|
0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
|
||||||
|
0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
|
||||||
|
0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
|
||||||
|
0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
|
||||||
|
0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
|
||||||
|
0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
|
||||||
|
0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
|
||||||
|
0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
|
||||||
|
0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
|
||||||
|
0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
|
||||||
|
0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
|
||||||
|
0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
|
||||||
|
0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
|
||||||
|
0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
|
||||||
|
0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
|
||||||
|
0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
|
||||||
|
0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
|
||||||
|
0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
|
||||||
|
0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
|
||||||
|
0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
|
||||||
|
0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
|
||||||
|
0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
|
||||||
|
0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
|
||||||
|
0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
|
||||||
|
0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
|
||||||
|
0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
|
||||||
|
0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
|
||||||
|
0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
|
||||||
|
0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
|
||||||
|
0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
|
||||||
|
0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
|
||||||
|
0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
|
||||||
|
0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
|
||||||
|
0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
|
||||||
|
0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
|
||||||
|
0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
|
||||||
|
0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
|
||||||
|
0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
|
||||||
|
0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
|
||||||
|
0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
|
||||||
|
0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
|
||||||
|
0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
|
||||||
|
0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
|
||||||
|
0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
|
||||||
|
0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
|
||||||
|
0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
|
||||||
|
0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
|
||||||
|
0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
|
||||||
|
0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
|
||||||
|
0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
|
||||||
|
0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
|
||||||
|
0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
|
||||||
|
0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
|
||||||
|
0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
|
||||||
|
0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
|
||||||
|
0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
|
||||||
|
0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
|
||||||
|
0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
|
||||||
|
0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
|
||||||
|
0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
|
||||||
|
0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
|
||||||
|
0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
|
||||||
|
0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
|
||||||
|
0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
|
||||||
|
0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
|
||||||
|
0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
|
||||||
|
0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
|
||||||
|
0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
|
||||||
|
0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
|
||||||
|
0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
|
||||||
|
0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
|
||||||
|
0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
|
||||||
|
0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
|
||||||
|
0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
|
||||||
|
0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
|
||||||
|
0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
|
||||||
|
0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
|
||||||
|
0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
|
||||||
|
0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
|
||||||
|
0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
|
||||||
|
0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
|
||||||
|
0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
|
||||||
|
0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
|
||||||
|
0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
|
||||||
|
0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
|
||||||
|
0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
|
||||||
|
0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
|
||||||
|
0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
|
||||||
|
0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
|
||||||
|
0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
|
||||||
|
0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
|
||||||
|
0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
|
||||||
|
0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
|
||||||
|
0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
|
||||||
|
0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
|
||||||
|
0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
|
||||||
|
0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
|
||||||
|
0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
|
||||||
|
0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
|
||||||
|
0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
|
||||||
|
0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
|
||||||
|
0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
|
||||||
|
0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
|
||||||
|
0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
|
||||||
|
0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
|
||||||
|
0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
|
||||||
|
0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
|
||||||
|
0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
|
||||||
|
0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
|
||||||
|
0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
|
||||||
|
0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
|
||||||
|
0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
|
||||||
|
0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
|
||||||
|
0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
|
||||||
|
0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
|
||||||
|
0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
|
||||||
|
0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
|
||||||
|
0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
|
||||||
|
0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
|
||||||
|
0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
|
||||||
|
0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
|
||||||
|
0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
|
||||||
|
0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
|
||||||
|
0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
|
||||||
|
0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
|
||||||
|
0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
|
||||||
|
0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
|
||||||
|
0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
|
||||||
|
0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
|
||||||
|
0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
|
||||||
|
0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
|
||||||
|
0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
|
||||||
|
0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
|
||||||
|
0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
|
||||||
|
0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
|
||||||
|
0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
|
||||||
|
0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
|
||||||
|
0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
|
||||||
|
0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
|
||||||
|
0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
|
||||||
|
0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
|
||||||
|
0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
|
||||||
|
0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
|
||||||
|
0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
|
||||||
|
0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
|
||||||
|
0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
|
||||||
|
0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
|
||||||
|
0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
|
||||||
|
0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
|
||||||
|
0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
|
||||||
|
0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
|
||||||
|
0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
|
||||||
|
0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
|
||||||
|
0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
|
||||||
|
0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
|
||||||
|
0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
|
||||||
|
0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
|
||||||
|
0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
|
||||||
|
0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
|
||||||
|
0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
|
||||||
|
0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
|
||||||
|
0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
|
||||||
|
0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
|
||||||
|
0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
|
||||||
|
0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
|
||||||
|
0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
|
||||||
|
0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
|
||||||
|
0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
|
||||||
|
0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
|
||||||
|
0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
|
||||||
|
0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
|
||||||
|
0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
|
||||||
|
0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
|
||||||
|
0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
|
||||||
|
0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
|
||||||
|
0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
|
||||||
|
0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
|
||||||
|
0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
|
||||||
|
0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
|
||||||
|
0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
|
||||||
|
0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
|
||||||
|
0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
|
||||||
|
0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e,
|
||||||
|
},
|
||||||
|
}
|
106
vendor/golang.org/x/crypto/cast5/cast5_test.go
generated
vendored
Normal file
106
vendor/golang.org/x/crypto/cast5/cast5_test.go
generated
vendored
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package cast5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This test vector is taken from RFC 2144, App B.1.
|
||||||
|
// Since the other two test vectors are for reduced-round variants, we can't
|
||||||
|
// use them.
|
||||||
|
var basicTests = []struct {
|
||||||
|
key, plainText, cipherText string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"0123456712345678234567893456789a",
|
||||||
|
"0123456789abcdef",
|
||||||
|
"238b4fe5847e44b2",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBasic(t *testing.T) {
|
||||||
|
for i, test := range basicTests {
|
||||||
|
key, _ := hex.DecodeString(test.key)
|
||||||
|
plainText, _ := hex.DecodeString(test.plainText)
|
||||||
|
expected, _ := hex.DecodeString(test.cipherText)
|
||||||
|
|
||||||
|
c, err := NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("#%d: failed to create Cipher: %s", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var cipherText [BlockSize]byte
|
||||||
|
c.Encrypt(cipherText[:], plainText)
|
||||||
|
if !bytes.Equal(cipherText[:], expected) {
|
||||||
|
t.Errorf("#%d: got:%x want:%x", i, cipherText, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
var plainTextAgain [BlockSize]byte
|
||||||
|
c.Decrypt(plainTextAgain[:], cipherText[:])
|
||||||
|
if !bytes.Equal(plainTextAgain[:], plainText) {
|
||||||
|
t.Errorf("#%d: got:%x want:%x", i, plainTextAgain, plainText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestFull performs the test specified in RFC 2144, App B.2.
|
||||||
|
// However, due to the length of time taken, it's disabled here and a more
|
||||||
|
// limited version is included, below.
|
||||||
|
func TestFull(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
// This is too slow for normal testing
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
a, b := iterate(1000000)
|
||||||
|
|
||||||
|
const expectedA = "eea9d0a249fd3ba6b3436fb89d6dca92"
|
||||||
|
const expectedB = "b2c95eb00c31ad7180ac05b8e83d696e"
|
||||||
|
|
||||||
|
if hex.EncodeToString(a) != expectedA {
|
||||||
|
t.Errorf("a: got:%x want:%s", a, expectedA)
|
||||||
|
}
|
||||||
|
if hex.EncodeToString(b) != expectedB {
|
||||||
|
t.Errorf("b: got:%x want:%s", b, expectedB)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func iterate(iterations int) ([]byte, []byte) {
|
||||||
|
const initValueHex = "0123456712345678234567893456789a"
|
||||||
|
|
||||||
|
initValue, _ := hex.DecodeString(initValueHex)
|
||||||
|
|
||||||
|
var a, b [16]byte
|
||||||
|
copy(a[:], initValue)
|
||||||
|
copy(b[:], initValue)
|
||||||
|
|
||||||
|
for i := 0; i < iterations; i++ {
|
||||||
|
c, _ := NewCipher(b[:])
|
||||||
|
c.Encrypt(a[:8], a[:8])
|
||||||
|
c.Encrypt(a[8:], a[8:])
|
||||||
|
c, _ = NewCipher(a[:])
|
||||||
|
c.Encrypt(b[:8], b[:8])
|
||||||
|
c.Encrypt(b[8:], b[8:])
|
||||||
|
}
|
||||||
|
|
||||||
|
return a[:], b[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLimited(t *testing.T) {
|
||||||
|
a, b := iterate(1000)
|
||||||
|
|
||||||
|
const expectedA = "23f73b14b02a2ad7dfb9f2c35644798d"
|
||||||
|
const expectedB = "e5bf37eff14c456a40b21ce369370a9f"
|
||||||
|
|
||||||
|
if hex.EncodeToString(a) != expectedA {
|
||||||
|
t.Errorf("a: got:%x want:%s", a, expectedA)
|
||||||
|
}
|
||||||
|
if hex.EncodeToString(b) != expectedB {
|
||||||
|
t.Errorf("b: got:%x want:%s", b, expectedB)
|
||||||
|
}
|
||||||
|
}
|
20
vendor/golang.org/x/crypto/curve25519/const_amd64.s
generated
vendored
Normal file
20
vendor/golang.org/x/crypto/curve25519/const_amd64.s
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This code was translated into a form compatible with 6a from the public
|
||||||
|
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||||
|
|
||||||
|
// +build amd64,!gccgo
|
||||||
|
|
||||||
|
DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF
|
||||||
|
GLOBL ·REDMASK51(SB), 8, $8
|
||||||
|
|
||||||
|
DATA ·_121666_213(SB)/8, $996687872
|
||||||
|
GLOBL ·_121666_213(SB), 8, $8
|
||||||
|
|
||||||
|
DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA
|
||||||
|
GLOBL ·_2P0(SB), 8, $8
|
||||||
|
|
||||||
|
DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE
|
||||||
|
GLOBL ·_2P1234(SB), 8, $8
|
88
vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
generated
vendored
Normal file
88
vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
generated
vendored
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This code was translated into a form compatible with 6a from the public
|
||||||
|
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||||
|
|
||||||
|
// +build amd64,!gccgo
|
||||||
|
|
||||||
|
// func cswap(inout *[5]uint64, v uint64)
|
||||||
|
TEXT ·cswap(SB),7,$0
|
||||||
|
MOVQ inout+0(FP),DI
|
||||||
|
MOVQ v+8(FP),SI
|
||||||
|
|
||||||
|
CMPQ SI,$1
|
||||||
|
MOVQ 0(DI),SI
|
||||||
|
MOVQ 80(DI),DX
|
||||||
|
MOVQ 8(DI),CX
|
||||||
|
MOVQ 88(DI),R8
|
||||||
|
MOVQ SI,R9
|
||||||
|
CMOVQEQ DX,SI
|
||||||
|
CMOVQEQ R9,DX
|
||||||
|
MOVQ CX,R9
|
||||||
|
CMOVQEQ R8,CX
|
||||||
|
CMOVQEQ R9,R8
|
||||||
|
MOVQ SI,0(DI)
|
||||||
|
MOVQ DX,80(DI)
|
||||||
|
MOVQ CX,8(DI)
|
||||||
|
MOVQ R8,88(DI)
|
||||||
|
MOVQ 16(DI),SI
|
||||||
|
MOVQ 96(DI),DX
|
||||||
|
MOVQ 24(DI),CX
|
||||||
|
MOVQ 104(DI),R8
|
||||||
|
MOVQ SI,R9
|
||||||
|
CMOVQEQ DX,SI
|
||||||
|
CMOVQEQ R9,DX
|
||||||
|
MOVQ CX,R9
|
||||||
|
CMOVQEQ R8,CX
|
||||||
|
CMOVQEQ R9,R8
|
||||||
|
MOVQ SI,16(DI)
|
||||||
|
MOVQ DX,96(DI)
|
||||||
|
MOVQ CX,24(DI)
|
||||||
|
MOVQ R8,104(DI)
|
||||||
|
MOVQ 32(DI),SI
|
||||||
|
MOVQ 112(DI),DX
|
||||||
|
MOVQ 40(DI),CX
|
||||||
|
MOVQ 120(DI),R8
|
||||||
|
MOVQ SI,R9
|
||||||
|
CMOVQEQ DX,SI
|
||||||
|
CMOVQEQ R9,DX
|
||||||
|
MOVQ CX,R9
|
||||||
|
CMOVQEQ R8,CX
|
||||||
|
CMOVQEQ R9,R8
|
||||||
|
MOVQ SI,32(DI)
|
||||||
|
MOVQ DX,112(DI)
|
||||||
|
MOVQ CX,40(DI)
|
||||||
|
MOVQ R8,120(DI)
|
||||||
|
MOVQ 48(DI),SI
|
||||||
|
MOVQ 128(DI),DX
|
||||||
|
MOVQ 56(DI),CX
|
||||||
|
MOVQ 136(DI),R8
|
||||||
|
MOVQ SI,R9
|
||||||
|
CMOVQEQ DX,SI
|
||||||
|
CMOVQEQ R9,DX
|
||||||
|
MOVQ CX,R9
|
||||||
|
CMOVQEQ R8,CX
|
||||||
|
CMOVQEQ R9,R8
|
||||||
|
MOVQ SI,48(DI)
|
||||||
|
MOVQ DX,128(DI)
|
||||||
|
MOVQ CX,56(DI)
|
||||||
|
MOVQ R8,136(DI)
|
||||||
|
MOVQ 64(DI),SI
|
||||||
|
MOVQ 144(DI),DX
|
||||||
|
MOVQ 72(DI),CX
|
||||||
|
MOVQ 152(DI),R8
|
||||||
|
MOVQ SI,R9
|
||||||
|
CMOVQEQ DX,SI
|
||||||
|
CMOVQEQ R9,DX
|
||||||
|
MOVQ CX,R9
|
||||||
|
CMOVQEQ R8,CX
|
||||||
|
CMOVQEQ R9,R8
|
||||||
|
MOVQ SI,64(DI)
|
||||||
|
MOVQ DX,144(DI)
|
||||||
|
MOVQ CX,72(DI)
|
||||||
|
MOVQ R8,152(DI)
|
||||||
|
MOVQ DI,AX
|
||||||
|
MOVQ SI,DX
|
||||||
|
RET
|
841
vendor/golang.org/x/crypto/curve25519/curve25519.go
generated
vendored
Normal file
841
vendor/golang.org/x/crypto/curve25519/curve25519.go
generated
vendored
Normal file
|
@ -0,0 +1,841 @@
|
||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// We have a implementation in amd64 assembly so this code is only run on
|
||||||
|
// non-amd64 platforms. The amd64 assembly does not support gccgo.
|
||||||
|
// +build !amd64 gccgo
|
||||||
|
|
||||||
|
package curve25519
|
||||||
|
|
||||||
|
// This code is a port of the public domain, "ref10" implementation of
|
||||||
|
// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
|
||||||
|
|
||||||
|
// fieldElement represents an element of the field GF(2^255 - 19). An element
|
||||||
|
// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
|
||||||
|
// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
|
||||||
|
// context.
|
||||||
|
type fieldElement [10]int32
|
||||||
|
|
||||||
|
func feZero(fe *fieldElement) {
|
||||||
|
for i := range fe {
|
||||||
|
fe[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func feOne(fe *fieldElement) {
|
||||||
|
feZero(fe)
|
||||||
|
fe[0] = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func feAdd(dst, a, b *fieldElement) {
|
||||||
|
for i := range dst {
|
||||||
|
dst[i] = a[i] + b[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func feSub(dst, a, b *fieldElement) {
|
||||||
|
for i := range dst {
|
||||||
|
dst[i] = a[i] - b[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func feCopy(dst, src *fieldElement) {
|
||||||
|
for i := range dst {
|
||||||
|
dst[i] = src[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0.
|
||||||
|
//
|
||||||
|
// Preconditions: b in {0,1}.
|
||||||
|
func feCSwap(f, g *fieldElement, b int32) {
|
||||||
|
var x fieldElement
|
||||||
|
b = -b
|
||||||
|
for i := range x {
|
||||||
|
x[i] = b & (f[i] ^ g[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range f {
|
||||||
|
f[i] ^= x[i]
|
||||||
|
}
|
||||||
|
for i := range g {
|
||||||
|
g[i] ^= x[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// load3 reads a 24-bit, little-endian value from in.
|
||||||
|
func load3(in []byte) int64 {
|
||||||
|
var r int64
|
||||||
|
r = int64(in[0])
|
||||||
|
r |= int64(in[1]) << 8
|
||||||
|
r |= int64(in[2]) << 16
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// load4 reads a 32-bit, little-endian value from in.
|
||||||
|
func load4(in []byte) int64 {
|
||||||
|
var r int64
|
||||||
|
r = int64(in[0])
|
||||||
|
r |= int64(in[1]) << 8
|
||||||
|
r |= int64(in[2]) << 16
|
||||||
|
r |= int64(in[3]) << 24
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func feFromBytes(dst *fieldElement, src *[32]byte) {
|
||||||
|
h0 := load4(src[:])
|
||||||
|
h1 := load3(src[4:]) << 6
|
||||||
|
h2 := load3(src[7:]) << 5
|
||||||
|
h3 := load3(src[10:]) << 3
|
||||||
|
h4 := load3(src[13:]) << 2
|
||||||
|
h5 := load4(src[16:])
|
||||||
|
h6 := load3(src[20:]) << 7
|
||||||
|
h7 := load3(src[23:]) << 5
|
||||||
|
h8 := load3(src[26:]) << 4
|
||||||
|
h9 := load3(src[29:]) << 2
|
||||||
|
|
||||||
|
var carry [10]int64
|
||||||
|
carry[9] = (h9 + 1<<24) >> 25
|
||||||
|
h0 += carry[9] * 19
|
||||||
|
h9 -= carry[9] << 25
|
||||||
|
carry[1] = (h1 + 1<<24) >> 25
|
||||||
|
h2 += carry[1]
|
||||||
|
h1 -= carry[1] << 25
|
||||||
|
carry[3] = (h3 + 1<<24) >> 25
|
||||||
|
h4 += carry[3]
|
||||||
|
h3 -= carry[3] << 25
|
||||||
|
carry[5] = (h5 + 1<<24) >> 25
|
||||||
|
h6 += carry[5]
|
||||||
|
h5 -= carry[5] << 25
|
||||||
|
carry[7] = (h7 + 1<<24) >> 25
|
||||||
|
h8 += carry[7]
|
||||||
|
h7 -= carry[7] << 25
|
||||||
|
|
||||||
|
carry[0] = (h0 + 1<<25) >> 26
|
||||||
|
h1 += carry[0]
|
||||||
|
h0 -= carry[0] << 26
|
||||||
|
carry[2] = (h2 + 1<<25) >> 26
|
||||||
|
h3 += carry[2]
|
||||||
|
h2 -= carry[2] << 26
|
||||||
|
carry[4] = (h4 + 1<<25) >> 26
|
||||||
|
h5 += carry[4]
|
||||||
|
h4 -= carry[4] << 26
|
||||||
|
carry[6] = (h6 + 1<<25) >> 26
|
||||||
|
h7 += carry[6]
|
||||||
|
h6 -= carry[6] << 26
|
||||||
|
carry[8] = (h8 + 1<<25) >> 26
|
||||||
|
h9 += carry[8]
|
||||||
|
h8 -= carry[8] << 26
|
||||||
|
|
||||||
|
dst[0] = int32(h0)
|
||||||
|
dst[1] = int32(h1)
|
||||||
|
dst[2] = int32(h2)
|
||||||
|
dst[3] = int32(h3)
|
||||||
|
dst[4] = int32(h4)
|
||||||
|
dst[5] = int32(h5)
|
||||||
|
dst[6] = int32(h6)
|
||||||
|
dst[7] = int32(h7)
|
||||||
|
dst[8] = int32(h8)
|
||||||
|
dst[9] = int32(h9)
|
||||||
|
}
|
||||||
|
|
||||||
|
// feToBytes marshals h to s.
|
||||||
|
// Preconditions:
|
||||||
|
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
||||||
|
//
|
||||||
|
// Write p=2^255-19; q=floor(h/p).
|
||||||
|
// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
|
||||||
|
//
|
||||||
|
// Proof:
|
||||||
|
// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
|
||||||
|
// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
|
||||||
|
//
|
||||||
|
// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
|
||||||
|
// Then 0<y<1.
|
||||||
|
//
|
||||||
|
// Write r=h-pq.
|
||||||
|
// Have 0<=r<=p-1=2^255-20.
|
||||||
|
// Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
|
||||||
|
//
|
||||||
|
// Write x=r+19(2^-255)r+y.
|
||||||
|
// Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
|
||||||
|
//
|
||||||
|
// Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
|
||||||
|
// so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
|
||||||
|
func feToBytes(s *[32]byte, h *fieldElement) {
|
||||||
|
var carry [10]int32
|
||||||
|
|
||||||
|
q := (19*h[9] + (1 << 24)) >> 25
|
||||||
|
q = (h[0] + q) >> 26
|
||||||
|
q = (h[1] + q) >> 25
|
||||||
|
q = (h[2] + q) >> 26
|
||||||
|
q = (h[3] + q) >> 25
|
||||||
|
q = (h[4] + q) >> 26
|
||||||
|
q = (h[5] + q) >> 25
|
||||||
|
q = (h[6] + q) >> 26
|
||||||
|
q = (h[7] + q) >> 25
|
||||||
|
q = (h[8] + q) >> 26
|
||||||
|
q = (h[9] + q) >> 25
|
||||||
|
|
||||||
|
// Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
|
||||||
|
h[0] += 19 * q
|
||||||
|
// Goal: Output h-2^255 q, which is between 0 and 2^255-20.
|
||||||
|
|
||||||
|
carry[0] = h[0] >> 26
|
||||||
|
h[1] += carry[0]
|
||||||
|
h[0] -= carry[0] << 26
|
||||||
|
carry[1] = h[1] >> 25
|
||||||
|
h[2] += carry[1]
|
||||||
|
h[1] -= carry[1] << 25
|
||||||
|
carry[2] = h[2] >> 26
|
||||||
|
h[3] += carry[2]
|
||||||
|
h[2] -= carry[2] << 26
|
||||||
|
carry[3] = h[3] >> 25
|
||||||
|
h[4] += carry[3]
|
||||||
|
h[3] -= carry[3] << 25
|
||||||
|
carry[4] = h[4] >> 26
|
||||||
|
h[5] += carry[4]
|
||||||
|
h[4] -= carry[4] << 26
|
||||||
|
carry[5] = h[5] >> 25
|
||||||
|
h[6] += carry[5]
|
||||||
|
h[5] -= carry[5] << 25
|
||||||
|
carry[6] = h[6] >> 26
|
||||||
|
h[7] += carry[6]
|
||||||
|
h[6] -= carry[6] << 26
|
||||||
|
carry[7] = h[7] >> 25
|
||||||
|
h[8] += carry[7]
|
||||||
|
h[7] -= carry[7] << 25
|
||||||
|
carry[8] = h[8] >> 26
|
||||||
|
h[9] += carry[8]
|
||||||
|
h[8] -= carry[8] << 26
|
||||||
|
carry[9] = h[9] >> 25
|
||||||
|
h[9] -= carry[9] << 25
|
||||||
|
// h10 = carry9
|
||||||
|
|
||||||
|
// Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
|
||||||
|
// Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
|
||||||
|
// evidently 2^255 h10-2^255 q = 0.
|
||||||
|
// Goal: Output h[0]+...+2^230 h[9].
|
||||||
|
|
||||||
|
s[0] = byte(h[0] >> 0)
|
||||||
|
s[1] = byte(h[0] >> 8)
|
||||||
|
s[2] = byte(h[0] >> 16)
|
||||||
|
s[3] = byte((h[0] >> 24) | (h[1] << 2))
|
||||||
|
s[4] = byte(h[1] >> 6)
|
||||||
|
s[5] = byte(h[1] >> 14)
|
||||||
|
s[6] = byte((h[1] >> 22) | (h[2] << 3))
|
||||||
|
s[7] = byte(h[2] >> 5)
|
||||||
|
s[8] = byte(h[2] >> 13)
|
||||||
|
s[9] = byte((h[2] >> 21) | (h[3] << 5))
|
||||||
|
s[10] = byte(h[3] >> 3)
|
||||||
|
s[11] = byte(h[3] >> 11)
|
||||||
|
s[12] = byte((h[3] >> 19) | (h[4] << 6))
|
||||||
|
s[13] = byte(h[4] >> 2)
|
||||||
|
s[14] = byte(h[4] >> 10)
|
||||||
|
s[15] = byte(h[4] >> 18)
|
||||||
|
s[16] = byte(h[5] >> 0)
|
||||||
|
s[17] = byte(h[5] >> 8)
|
||||||
|
s[18] = byte(h[5] >> 16)
|
||||||
|
s[19] = byte((h[5] >> 24) | (h[6] << 1))
|
||||||
|
s[20] = byte(h[6] >> 7)
|
||||||
|
s[21] = byte(h[6] >> 15)
|
||||||
|
s[22] = byte((h[6] >> 23) | (h[7] << 3))
|
||||||
|
s[23] = byte(h[7] >> 5)
|
||||||
|
s[24] = byte(h[7] >> 13)
|
||||||
|
s[25] = byte((h[7] >> 21) | (h[8] << 4))
|
||||||
|
s[26] = byte(h[8] >> 4)
|
||||||
|
s[27] = byte(h[8] >> 12)
|
||||||
|
s[28] = byte((h[8] >> 20) | (h[9] << 6))
|
||||||
|
s[29] = byte(h[9] >> 2)
|
||||||
|
s[30] = byte(h[9] >> 10)
|
||||||
|
s[31] = byte(h[9] >> 18)
|
||||||
|
}
|
||||||
|
|
||||||
|
// feMul calculates h = f * g
|
||||||
|
// Can overlap h with f or g.
|
||||||
|
//
|
||||||
|
// Preconditions:
|
||||||
|
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
||||||
|
// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
||||||
|
//
|
||||||
|
// Postconditions:
|
||||||
|
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
||||||
|
//
|
||||||
|
// Notes on implementation strategy:
|
||||||
|
//
|
||||||
|
// Using schoolbook multiplication.
|
||||||
|
// Karatsuba would save a little in some cost models.
|
||||||
|
//
|
||||||
|
// Most multiplications by 2 and 19 are 32-bit precomputations;
|
||||||
|
// cheaper than 64-bit postcomputations.
|
||||||
|
//
|
||||||
|
// There is one remaining multiplication by 19 in the carry chain;
|
||||||
|
// one *19 precomputation can be merged into this,
|
||||||
|
// but the resulting data flow is considerably less clean.
|
||||||
|
//
|
||||||
|
// There are 12 carries below.
|
||||||
|
// 10 of them are 2-way parallelizable and vectorizable.
|
||||||
|
// Can get away with 11 carries, but then data flow is much deeper.
|
||||||
|
//
|
||||||
|
// With tighter constraints on inputs can squeeze carries into int32.
|
||||||
|
func feMul(h, f, g *fieldElement) {
|
||||||
|
f0 := f[0]
|
||||||
|
f1 := f[1]
|
||||||
|
f2 := f[2]
|
||||||
|
f3 := f[3]
|
||||||
|
f4 := f[4]
|
||||||
|
f5 := f[5]
|
||||||
|
f6 := f[6]
|
||||||
|
f7 := f[7]
|
||||||
|
f8 := f[8]
|
||||||
|
f9 := f[9]
|
||||||
|
g0 := g[0]
|
||||||
|
g1 := g[1]
|
||||||
|
g2 := g[2]
|
||||||
|
g3 := g[3]
|
||||||
|
g4 := g[4]
|
||||||
|
g5 := g[5]
|
||||||
|
g6 := g[6]
|
||||||
|
g7 := g[7]
|
||||||
|
g8 := g[8]
|
||||||
|
g9 := g[9]
|
||||||
|
g1_19 := 19 * g1 // 1.4*2^29
|
||||||
|
g2_19 := 19 * g2 // 1.4*2^30; still ok
|
||||||
|
g3_19 := 19 * g3
|
||||||
|
g4_19 := 19 * g4
|
||||||
|
g5_19 := 19 * g5
|
||||||
|
g6_19 := 19 * g6
|
||||||
|
g7_19 := 19 * g7
|
||||||
|
g8_19 := 19 * g8
|
||||||
|
g9_19 := 19 * g9
|
||||||
|
f1_2 := 2 * f1
|
||||||
|
f3_2 := 2 * f3
|
||||||
|
f5_2 := 2 * f5
|
||||||
|
f7_2 := 2 * f7
|
||||||
|
f9_2 := 2 * f9
|
||||||
|
f0g0 := int64(f0) * int64(g0)
|
||||||
|
f0g1 := int64(f0) * int64(g1)
|
||||||
|
f0g2 := int64(f0) * int64(g2)
|
||||||
|
f0g3 := int64(f0) * int64(g3)
|
||||||
|
f0g4 := int64(f0) * int64(g4)
|
||||||
|
f0g5 := int64(f0) * int64(g5)
|
||||||
|
f0g6 := int64(f0) * int64(g6)
|
||||||
|
f0g7 := int64(f0) * int64(g7)
|
||||||
|
f0g8 := int64(f0) * int64(g8)
|
||||||
|
f0g9 := int64(f0) * int64(g9)
|
||||||
|
f1g0 := int64(f1) * int64(g0)
|
||||||
|
f1g1_2 := int64(f1_2) * int64(g1)
|
||||||
|
f1g2 := int64(f1) * int64(g2)
|
||||||
|
f1g3_2 := int64(f1_2) * int64(g3)
|
||||||
|
f1g4 := int64(f1) * int64(g4)
|
||||||
|
f1g5_2 := int64(f1_2) * int64(g5)
|
||||||
|
f1g6 := int64(f1) * int64(g6)
|
||||||
|
f1g7_2 := int64(f1_2) * int64(g7)
|
||||||
|
f1g8 := int64(f1) * int64(g8)
|
||||||
|
f1g9_38 := int64(f1_2) * int64(g9_19)
|
||||||
|
f2g0 := int64(f2) * int64(g0)
|
||||||
|
f2g1 := int64(f2) * int64(g1)
|
||||||
|
f2g2 := int64(f2) * int64(g2)
|
||||||
|
f2g3 := int64(f2) * int64(g3)
|
||||||
|
f2g4 := int64(f2) * int64(g4)
|
||||||
|
f2g5 := int64(f2) * int64(g5)
|
||||||
|
f2g6 := int64(f2) * int64(g6)
|
||||||
|
f2g7 := int64(f2) * int64(g7)
|
||||||
|
f2g8_19 := int64(f2) * int64(g8_19)
|
||||||
|
f2g9_19 := int64(f2) * int64(g9_19)
|
||||||
|
f3g0 := int64(f3) * int64(g0)
|
||||||
|
f3g1_2 := int64(f3_2) * int64(g1)
|
||||||
|
f3g2 := int64(f3) * int64(g2)
|
||||||
|
f3g3_2 := int64(f3_2) * int64(g3)
|
||||||
|
f3g4 := int64(f3) * int64(g4)
|
||||||
|
f3g5_2 := int64(f3_2) * int64(g5)
|
||||||
|
f3g6 := int64(f3) * int64(g6)
|
||||||
|
f3g7_38 := int64(f3_2) * int64(g7_19)
|
||||||
|
f3g8_19 := int64(f3) * int64(g8_19)
|
||||||
|
f3g9_38 := int64(f3_2) * int64(g9_19)
|
||||||
|
f4g0 := int64(f4) * int64(g0)
|
||||||
|
f4g1 := int64(f4) * int64(g1)
|
||||||
|
f4g2 := int64(f4) * int64(g2)
|
||||||
|
f4g3 := int64(f4) * int64(g3)
|
||||||
|
f4g4 := int64(f4) * int64(g4)
|
||||||
|
f4g5 := int64(f4) * int64(g5)
|
||||||
|
f4g6_19 := int64(f4) * int64(g6_19)
|
||||||
|
f4g7_19 := int64(f4) * int64(g7_19)
|
||||||
|
f4g8_19 := int64(f4) * int64(g8_19)
|
||||||
|
f4g9_19 := int64(f4) * int64(g9_19)
|
||||||
|
f5g0 := int64(f5) * int64(g0)
|
||||||
|
f5g1_2 := int64(f5_2) * int64(g1)
|
||||||
|
f5g2 := int64(f5) * int64(g2)
|
||||||
|
f5g3_2 := int64(f5_2) * int64(g3)
|
||||||
|
f5g4 := int64(f5) * int64(g4)
|
||||||
|
f5g5_38 := int64(f5_2) * int64(g5_19)
|
||||||
|
f5g6_19 := int64(f5) * int64(g6_19)
|
||||||
|
f5g7_38 := int64(f5_2) * int64(g7_19)
|
||||||
|
f5g8_19 := int64(f5) * int64(g8_19)
|
||||||
|
f5g9_38 := int64(f5_2) * int64(g9_19)
|
||||||
|
f6g0 := int64(f6) * int64(g0)
|
||||||
|
f6g1 := int64(f6) * int64(g1)
|
||||||
|
f6g2 := int64(f6) * int64(g2)
|
||||||
|
f6g3 := int64(f6) * int64(g3)
|
||||||
|
f6g4_19 := int64(f6) * int64(g4_19)
|
||||||
|
f6g5_19 := int64(f6) * int64(g5_19)
|
||||||
|
f6g6_19 := int64(f6) * int64(g6_19)
|
||||||
|
f6g7_19 := int64(f6) * int64(g7_19)
|
||||||
|
f6g8_19 := int64(f6) * int64(g8_19)
|
||||||
|
f6g9_19 := int64(f6) * int64(g9_19)
|
||||||
|
f7g0 := int64(f7) * int64(g0)
|
||||||
|
f7g1_2 := int64(f7_2) * int64(g1)
|
||||||
|
f7g2 := int64(f7) * int64(g2)
|
||||||
|
f7g3_38 := int64(f7_2) * int64(g3_19)
|
||||||
|
f7g4_19 := int64(f7) * int64(g4_19)
|
||||||
|
f7g5_38 := int64(f7_2) * int64(g5_19)
|
||||||
|
f7g6_19 := int64(f7) * int64(g6_19)
|
||||||
|
f7g7_38 := int64(f7_2) * int64(g7_19)
|
||||||
|
f7g8_19 := int64(f7) * int64(g8_19)
|
||||||
|
f7g9_38 := int64(f7_2) * int64(g9_19)
|
||||||
|
f8g0 := int64(f8) * int64(g0)
|
||||||
|
f8g1 := int64(f8) * int64(g1)
|
||||||
|
f8g2_19 := int64(f8) * int64(g2_19)
|
||||||
|
f8g3_19 := int64(f8) * int64(g3_19)
|
||||||
|
f8g4_19 := int64(f8) * int64(g4_19)
|
||||||
|
f8g5_19 := int64(f8) * int64(g5_19)
|
||||||
|
f8g6_19 := int64(f8) * int64(g6_19)
|
||||||
|
f8g7_19 := int64(f8) * int64(g7_19)
|
||||||
|
f8g8_19 := int64(f8) * int64(g8_19)
|
||||||
|
f8g9_19 := int64(f8) * int64(g9_19)
|
||||||
|
f9g0 := int64(f9) * int64(g0)
|
||||||
|
f9g1_38 := int64(f9_2) * int64(g1_19)
|
||||||
|
f9g2_19 := int64(f9) * int64(g2_19)
|
||||||
|
f9g3_38 := int64(f9_2) * int64(g3_19)
|
||||||
|
f9g4_19 := int64(f9) * int64(g4_19)
|
||||||
|
f9g5_38 := int64(f9_2) * int64(g5_19)
|
||||||
|
f9g6_19 := int64(f9) * int64(g6_19)
|
||||||
|
f9g7_38 := int64(f9_2) * int64(g7_19)
|
||||||
|
f9g8_19 := int64(f9) * int64(g8_19)
|
||||||
|
f9g9_38 := int64(f9_2) * int64(g9_19)
|
||||||
|
h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38
|
||||||
|
h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19
|
||||||
|
h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38
|
||||||
|
h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19
|
||||||
|
h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38
|
||||||
|
h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19
|
||||||
|
h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38
|
||||||
|
h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19
|
||||||
|
h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38
|
||||||
|
h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0
|
||||||
|
var carry [10]int64
|
||||||
|
|
||||||
|
// |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
|
||||||
|
// i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
|
||||||
|
// |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
|
||||||
|
// i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
|
||||||
|
|
||||||
|
carry[0] = (h0 + (1 << 25)) >> 26
|
||||||
|
h1 += carry[0]
|
||||||
|
h0 -= carry[0] << 26
|
||||||
|
carry[4] = (h4 + (1 << 25)) >> 26
|
||||||
|
h5 += carry[4]
|
||||||
|
h4 -= carry[4] << 26
|
||||||
|
// |h0| <= 2^25
|
||||||
|
// |h4| <= 2^25
|
||||||
|
// |h1| <= 1.51*2^58
|
||||||
|
// |h5| <= 1.51*2^58
|
||||||
|
|
||||||
|
carry[1] = (h1 + (1 << 24)) >> 25
|
||||||
|
h2 += carry[1]
|
||||||
|
h1 -= carry[1] << 25
|
||||||
|
carry[5] = (h5 + (1 << 24)) >> 25
|
||||||
|
h6 += carry[5]
|
||||||
|
h5 -= carry[5] << 25
|
||||||
|
// |h1| <= 2^24; from now on fits into int32
|
||||||
|
// |h5| <= 2^24; from now on fits into int32
|
||||||
|
// |h2| <= 1.21*2^59
|
||||||
|
// |h6| <= 1.21*2^59
|
||||||
|
|
||||||
|
carry[2] = (h2 + (1 << 25)) >> 26
|
||||||
|
h3 += carry[2]
|
||||||
|
h2 -= carry[2] << 26
|
||||||
|
carry[6] = (h6 + (1 << 25)) >> 26
|
||||||
|
h7 += carry[6]
|
||||||
|
h6 -= carry[6] << 26
|
||||||
|
// |h2| <= 2^25; from now on fits into int32 unchanged
|
||||||
|
// |h6| <= 2^25; from now on fits into int32 unchanged
|
||||||
|
// |h3| <= 1.51*2^58
|
||||||
|
// |h7| <= 1.51*2^58
|
||||||
|
|
||||||
|
carry[3] = (h3 + (1 << 24)) >> 25
|
||||||
|
h4 += carry[3]
|
||||||
|
h3 -= carry[3] << 25
|
||||||
|
carry[7] = (h7 + (1 << 24)) >> 25
|
||||||
|
h8 += carry[7]
|
||||||
|
h7 -= carry[7] << 25
|
||||||
|
// |h3| <= 2^24; from now on fits into int32 unchanged
|
||||||
|
// |h7| <= 2^24; from now on fits into int32 unchanged
|
||||||
|
// |h4| <= 1.52*2^33
|
||||||
|
// |h8| <= 1.52*2^33
|
||||||
|
|
||||||
|
carry[4] = (h4 + (1 << 25)) >> 26
|
||||||
|
h5 += carry[4]
|
||||||
|
h4 -= carry[4] << 26
|
||||||
|
carry[8] = (h8 + (1 << 25)) >> 26
|
||||||
|
h9 += carry[8]
|
||||||
|
h8 -= carry[8] << 26
|
||||||
|
// |h4| <= 2^25; from now on fits into int32 unchanged
|
||||||
|
// |h8| <= 2^25; from now on fits into int32 unchanged
|
||||||
|
// |h5| <= 1.01*2^24
|
||||||
|
// |h9| <= 1.51*2^58
|
||||||
|
|
||||||
|
carry[9] = (h9 + (1 << 24)) >> 25
|
||||||
|
h0 += carry[9] * 19
|
||||||
|
h9 -= carry[9] << 25
|
||||||
|
// |h9| <= 2^24; from now on fits into int32 unchanged
|
||||||
|
// |h0| <= 1.8*2^37
|
||||||
|
|
||||||
|
carry[0] = (h0 + (1 << 25)) >> 26
|
||||||
|
h1 += carry[0]
|
||||||
|
h0 -= carry[0] << 26
|
||||||
|
// |h0| <= 2^25; from now on fits into int32 unchanged
|
||||||
|
// |h1| <= 1.01*2^24
|
||||||
|
|
||||||
|
h[0] = int32(h0)
|
||||||
|
h[1] = int32(h1)
|
||||||
|
h[2] = int32(h2)
|
||||||
|
h[3] = int32(h3)
|
||||||
|
h[4] = int32(h4)
|
||||||
|
h[5] = int32(h5)
|
||||||
|
h[6] = int32(h6)
|
||||||
|
h[7] = int32(h7)
|
||||||
|
h[8] = int32(h8)
|
||||||
|
h[9] = int32(h9)
|
||||||
|
}
|
||||||
|
|
||||||
|
// feSquare calculates h = f*f. Can overlap h with f.
|
||||||
|
//
|
||||||
|
// Preconditions:
|
||||||
|
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
||||||
|
//
|
||||||
|
// Postconditions:
|
||||||
|
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
||||||
|
func feSquare(h, f *fieldElement) {
|
||||||
|
f0 := f[0]
|
||||||
|
f1 := f[1]
|
||||||
|
f2 := f[2]
|
||||||
|
f3 := f[3]
|
||||||
|
f4 := f[4]
|
||||||
|
f5 := f[5]
|
||||||
|
f6 := f[6]
|
||||||
|
f7 := f[7]
|
||||||
|
f8 := f[8]
|
||||||
|
f9 := f[9]
|
||||||
|
f0_2 := 2 * f0
|
||||||
|
f1_2 := 2 * f1
|
||||||
|
f2_2 := 2 * f2
|
||||||
|
f3_2 := 2 * f3
|
||||||
|
f4_2 := 2 * f4
|
||||||
|
f5_2 := 2 * f5
|
||||||
|
f6_2 := 2 * f6
|
||||||
|
f7_2 := 2 * f7
|
||||||
|
f5_38 := 38 * f5 // 1.31*2^30
|
||||||
|
f6_19 := 19 * f6 // 1.31*2^30
|
||||||
|
f7_38 := 38 * f7 // 1.31*2^30
|
||||||
|
f8_19 := 19 * f8 // 1.31*2^30
|
||||||
|
f9_38 := 38 * f9 // 1.31*2^30
|
||||||
|
f0f0 := int64(f0) * int64(f0)
|
||||||
|
f0f1_2 := int64(f0_2) * int64(f1)
|
||||||
|
f0f2_2 := int64(f0_2) * int64(f2)
|
||||||
|
f0f3_2 := int64(f0_2) * int64(f3)
|
||||||
|
f0f4_2 := int64(f0_2) * int64(f4)
|
||||||
|
f0f5_2 := int64(f0_2) * int64(f5)
|
||||||
|
f0f6_2 := int64(f0_2) * int64(f6)
|
||||||
|
f0f7_2 := int64(f0_2) * int64(f7)
|
||||||
|
f0f8_2 := int64(f0_2) * int64(f8)
|
||||||
|
f0f9_2 := int64(f0_2) * int64(f9)
|
||||||
|
f1f1_2 := int64(f1_2) * int64(f1)
|
||||||
|
f1f2_2 := int64(f1_2) * int64(f2)
|
||||||
|
f1f3_4 := int64(f1_2) * int64(f3_2)
|
||||||
|
f1f4_2 := int64(f1_2) * int64(f4)
|
||||||
|
f1f5_4 := int64(f1_2) * int64(f5_2)
|
||||||
|
f1f6_2 := int64(f1_2) * int64(f6)
|
||||||
|
f1f7_4 := int64(f1_2) * int64(f7_2)
|
||||||
|
f1f8_2 := int64(f1_2) * int64(f8)
|
||||||
|
f1f9_76 := int64(f1_2) * int64(f9_38)
|
||||||
|
f2f2 := int64(f2) * int64(f2)
|
||||||
|
f2f3_2 := int64(f2_2) * int64(f3)
|
||||||
|
f2f4_2 := int64(f2_2) * int64(f4)
|
||||||
|
f2f5_2 := int64(f2_2) * int64(f5)
|
||||||
|
f2f6_2 := int64(f2_2) * int64(f6)
|
||||||
|
f2f7_2 := int64(f2_2) * int64(f7)
|
||||||
|
f2f8_38 := int64(f2_2) * int64(f8_19)
|
||||||
|
f2f9_38 := int64(f2) * int64(f9_38)
|
||||||
|
f3f3_2 := int64(f3_2) * int64(f3)
|
||||||
|
f3f4_2 := int64(f3_2) * int64(f4)
|
||||||
|
f3f5_4 := int64(f3_2) * int64(f5_2)
|
||||||
|
f3f6_2 := int64(f3_2) * int64(f6)
|
||||||
|
f3f7_76 := int64(f3_2) * int64(f7_38)
|
||||||
|
f3f8_38 := int64(f3_2) * int64(f8_19)
|
||||||
|
f3f9_76 := int64(f3_2) * int64(f9_38)
|
||||||
|
f4f4 := int64(f4) * int64(f4)
|
||||||
|
f4f5_2 := int64(f4_2) * int64(f5)
|
||||||
|
f4f6_38 := int64(f4_2) * int64(f6_19)
|
||||||
|
f4f7_38 := int64(f4) * int64(f7_38)
|
||||||
|
f4f8_38 := int64(f4_2) * int64(f8_19)
|
||||||
|
f4f9_38 := int64(f4) * int64(f9_38)
|
||||||
|
f5f5_38 := int64(f5) * int64(f5_38)
|
||||||
|
f5f6_38 := int64(f5_2) * int64(f6_19)
|
||||||
|
f5f7_76 := int64(f5_2) * int64(f7_38)
|
||||||
|
f5f8_38 := int64(f5_2) * int64(f8_19)
|
||||||
|
f5f9_76 := int64(f5_2) * int64(f9_38)
|
||||||
|
f6f6_19 := int64(f6) * int64(f6_19)
|
||||||
|
f6f7_38 := int64(f6) * int64(f7_38)
|
||||||
|
f6f8_38 := int64(f6_2) * int64(f8_19)
|
||||||
|
f6f9_38 := int64(f6) * int64(f9_38)
|
||||||
|
f7f7_38 := int64(f7) * int64(f7_38)
|
||||||
|
f7f8_38 := int64(f7_2) * int64(f8_19)
|
||||||
|
f7f9_76 := int64(f7_2) * int64(f9_38)
|
||||||
|
f8f8_19 := int64(f8) * int64(f8_19)
|
||||||
|
f8f9_38 := int64(f8) * int64(f9_38)
|
||||||
|
f9f9_38 := int64(f9) * int64(f9_38)
|
||||||
|
h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38
|
||||||
|
h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38
|
||||||
|
h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19
|
||||||
|
h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38
|
||||||
|
h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38
|
||||||
|
h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38
|
||||||
|
h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19
|
||||||
|
h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38
|
||||||
|
h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38
|
||||||
|
h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2
|
||||||
|
var carry [10]int64
|
||||||
|
|
||||||
|
carry[0] = (h0 + (1 << 25)) >> 26
|
||||||
|
h1 += carry[0]
|
||||||
|
h0 -= carry[0] << 26
|
||||||
|
carry[4] = (h4 + (1 << 25)) >> 26
|
||||||
|
h5 += carry[4]
|
||||||
|
h4 -= carry[4] << 26
|
||||||
|
|
||||||
|
carry[1] = (h1 + (1 << 24)) >> 25
|
||||||
|
h2 += carry[1]
|
||||||
|
h1 -= carry[1] << 25
|
||||||
|
carry[5] = (h5 + (1 << 24)) >> 25
|
||||||
|
h6 += carry[5]
|
||||||
|
h5 -= carry[5] << 25
|
||||||
|
|
||||||
|
carry[2] = (h2 + (1 << 25)) >> 26
|
||||||
|
h3 += carry[2]
|
||||||
|
h2 -= carry[2] << 26
|
||||||
|
carry[6] = (h6 + (1 << 25)) >> 26
|
||||||
|
h7 += carry[6]
|
||||||
|
h6 -= carry[6] << 26
|
||||||
|
|
||||||
|
carry[3] = (h3 + (1 << 24)) >> 25
|
||||||
|
h4 += carry[3]
|
||||||
|
h3 -= carry[3] << 25
|
||||||
|
carry[7] = (h7 + (1 << 24)) >> 25
|
||||||
|
h8 += carry[7]
|
||||||
|
h7 -= carry[7] << 25
|
||||||
|
|
||||||
|
carry[4] = (h4 + (1 << 25)) >> 26
|
||||||
|
h5 += carry[4]
|
||||||
|
h4 -= carry[4] << 26
|
||||||
|
carry[8] = (h8 + (1 << 25)) >> 26
|
||||||
|
h9 += carry[8]
|
||||||
|
h8 -= carry[8] << 26
|
||||||
|
|
||||||
|
carry[9] = (h9 + (1 << 24)) >> 25
|
||||||
|
h0 += carry[9] * 19
|
||||||
|
h9 -= carry[9] << 25
|
||||||
|
|
||||||
|
carry[0] = (h0 + (1 << 25)) >> 26
|
||||||
|
h1 += carry[0]
|
||||||
|
h0 -= carry[0] << 26
|
||||||
|
|
||||||
|
h[0] = int32(h0)
|
||||||
|
h[1] = int32(h1)
|
||||||
|
h[2] = int32(h2)
|
||||||
|
h[3] = int32(h3)
|
||||||
|
h[4] = int32(h4)
|
||||||
|
h[5] = int32(h5)
|
||||||
|
h[6] = int32(h6)
|
||||||
|
h[7] = int32(h7)
|
||||||
|
h[8] = int32(h8)
|
||||||
|
h[9] = int32(h9)
|
||||||
|
}
|
||||||
|
|
||||||
|
// feMul121666 calculates h = f * 121666. Can overlap h with f.
|
||||||
|
//
|
||||||
|
// Preconditions:
|
||||||
|
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
||||||
|
//
|
||||||
|
// Postconditions:
|
||||||
|
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
||||||
|
func feMul121666(h, f *fieldElement) {
|
||||||
|
h0 := int64(f[0]) * 121666
|
||||||
|
h1 := int64(f[1]) * 121666
|
||||||
|
h2 := int64(f[2]) * 121666
|
||||||
|
h3 := int64(f[3]) * 121666
|
||||||
|
h4 := int64(f[4]) * 121666
|
||||||
|
h5 := int64(f[5]) * 121666
|
||||||
|
h6 := int64(f[6]) * 121666
|
||||||
|
h7 := int64(f[7]) * 121666
|
||||||
|
h8 := int64(f[8]) * 121666
|
||||||
|
h9 := int64(f[9]) * 121666
|
||||||
|
var carry [10]int64
|
||||||
|
|
||||||
|
carry[9] = (h9 + (1 << 24)) >> 25
|
||||||
|
h0 += carry[9] * 19
|
||||||
|
h9 -= carry[9] << 25
|
||||||
|
carry[1] = (h1 + (1 << 24)) >> 25
|
||||||
|
h2 += carry[1]
|
||||||
|
h1 -= carry[1] << 25
|
||||||
|
carry[3] = (h3 + (1 << 24)) >> 25
|
||||||
|
h4 += carry[3]
|
||||||
|
h3 -= carry[3] << 25
|
||||||
|
carry[5] = (h5 + (1 << 24)) >> 25
|
||||||
|
h6 += carry[5]
|
||||||
|
h5 -= carry[5] << 25
|
||||||
|
carry[7] = (h7 + (1 << 24)) >> 25
|
||||||
|
h8 += carry[7]
|
||||||
|
h7 -= carry[7] << 25
|
||||||
|
|
||||||
|
carry[0] = (h0 + (1 << 25)) >> 26
|
||||||
|
h1 += carry[0]
|
||||||
|
h0 -= carry[0] << 26
|
||||||
|
carry[2] = (h2 + (1 << 25)) >> 26
|
||||||
|
h3 += carry[2]
|
||||||
|
h2 -= carry[2] << 26
|
||||||
|
carry[4] = (h4 + (1 << 25)) >> 26
|
||||||
|
h5 += carry[4]
|
||||||
|
h4 -= carry[4] << 26
|
||||||
|
carry[6] = (h6 + (1 << 25)) >> 26
|
||||||
|
h7 += carry[6]
|
||||||
|
h6 -= carry[6] << 26
|
||||||
|
carry[8] = (h8 + (1 << 25)) >> 26
|
||||||
|
h9 += carry[8]
|
||||||
|
h8 -= carry[8] << 26
|
||||||
|
|
||||||
|
h[0] = int32(h0)
|
||||||
|
h[1] = int32(h1)
|
||||||
|
h[2] = int32(h2)
|
||||||
|
h[3] = int32(h3)
|
||||||
|
h[4] = int32(h4)
|
||||||
|
h[5] = int32(h5)
|
||||||
|
h[6] = int32(h6)
|
||||||
|
h[7] = int32(h7)
|
||||||
|
h[8] = int32(h8)
|
||||||
|
h[9] = int32(h9)
|
||||||
|
}
|
||||||
|
|
||||||
|
// feInvert sets out = z^-1.
|
||||||
|
func feInvert(out, z *fieldElement) {
|
||||||
|
var t0, t1, t2, t3 fieldElement
|
||||||
|
var i int
|
||||||
|
|
||||||
|
feSquare(&t0, z)
|
||||||
|
for i = 1; i < 1; i++ {
|
||||||
|
feSquare(&t0, &t0)
|
||||||
|
}
|
||||||
|
feSquare(&t1, &t0)
|
||||||
|
for i = 1; i < 2; i++ {
|
||||||
|
feSquare(&t1, &t1)
|
||||||
|
}
|
||||||
|
feMul(&t1, z, &t1)
|
||||||
|
feMul(&t0, &t0, &t1)
|
||||||
|
feSquare(&t2, &t0)
|
||||||
|
for i = 1; i < 1; i++ {
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
}
|
||||||
|
feMul(&t1, &t1, &t2)
|
||||||
|
feSquare(&t2, &t1)
|
||||||
|
for i = 1; i < 5; i++ {
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
}
|
||||||
|
feMul(&t1, &t2, &t1)
|
||||||
|
feSquare(&t2, &t1)
|
||||||
|
for i = 1; i < 10; i++ {
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
}
|
||||||
|
feMul(&t2, &t2, &t1)
|
||||||
|
feSquare(&t3, &t2)
|
||||||
|
for i = 1; i < 20; i++ {
|
||||||
|
feSquare(&t3, &t3)
|
||||||
|
}
|
||||||
|
feMul(&t2, &t3, &t2)
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
for i = 1; i < 10; i++ {
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
}
|
||||||
|
feMul(&t1, &t2, &t1)
|
||||||
|
feSquare(&t2, &t1)
|
||||||
|
for i = 1; i < 50; i++ {
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
}
|
||||||
|
feMul(&t2, &t2, &t1)
|
||||||
|
feSquare(&t3, &t2)
|
||||||
|
for i = 1; i < 100; i++ {
|
||||||
|
feSquare(&t3, &t3)
|
||||||
|
}
|
||||||
|
feMul(&t2, &t3, &t2)
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
for i = 1; i < 50; i++ {
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
}
|
||||||
|
feMul(&t1, &t2, &t1)
|
||||||
|
feSquare(&t1, &t1)
|
||||||
|
for i = 1; i < 5; i++ {
|
||||||
|
feSquare(&t1, &t1)
|
||||||
|
}
|
||||||
|
feMul(out, &t1, &t0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func scalarMult(out, in, base *[32]byte) {
|
||||||
|
var e [32]byte
|
||||||
|
|
||||||
|
copy(e[:], in[:])
|
||||||
|
e[0] &= 248
|
||||||
|
e[31] &= 127
|
||||||
|
e[31] |= 64
|
||||||
|
|
||||||
|
var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement
|
||||||
|
feFromBytes(&x1, base)
|
||||||
|
feOne(&x2)
|
||||||
|
feCopy(&x3, &x1)
|
||||||
|
feOne(&z3)
|
||||||
|
|
||||||
|
swap := int32(0)
|
||||||
|
for pos := 254; pos >= 0; pos-- {
|
||||||
|
b := e[pos/8] >> uint(pos&7)
|
||||||
|
b &= 1
|
||||||
|
swap ^= int32(b)
|
||||||
|
feCSwap(&x2, &x3, swap)
|
||||||
|
feCSwap(&z2, &z3, swap)
|
||||||
|
swap = int32(b)
|
||||||
|
|
||||||
|
feSub(&tmp0, &x3, &z3)
|
||||||
|
feSub(&tmp1, &x2, &z2)
|
||||||
|
feAdd(&x2, &x2, &z2)
|
||||||
|
feAdd(&z2, &x3, &z3)
|
||||||
|
feMul(&z3, &tmp0, &x2)
|
||||||
|
feMul(&z2, &z2, &tmp1)
|
||||||
|
feSquare(&tmp0, &tmp1)
|
||||||
|
feSquare(&tmp1, &x2)
|
||||||
|
feAdd(&x3, &z3, &z2)
|
||||||
|
feSub(&z2, &z3, &z2)
|
||||||
|
feMul(&x2, &tmp1, &tmp0)
|
||||||
|
feSub(&tmp1, &tmp1, &tmp0)
|
||||||
|
feSquare(&z2, &z2)
|
||||||
|
feMul121666(&z3, &tmp1)
|
||||||
|
feSquare(&x3, &x3)
|
||||||
|
feAdd(&tmp0, &tmp0, &z3)
|
||||||
|
feMul(&z3, &x1, &z2)
|
||||||
|
feMul(&z2, &tmp1, &tmp0)
|
||||||
|
}
|
||||||
|
|
||||||
|
feCSwap(&x2, &x3, swap)
|
||||||
|
feCSwap(&z2, &z3, swap)
|
||||||
|
|
||||||
|
feInvert(&z2, &z2)
|
||||||
|
feMul(&x2, &x2, &z2)
|
||||||
|
feToBytes(out, &x2)
|
||||||
|
}
|
29
vendor/golang.org/x/crypto/curve25519/curve25519_test.go
generated
vendored
Normal file
29
vendor/golang.org/x/crypto/curve25519/curve25519_test.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package curve25519
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a"
|
||||||
|
|
||||||
|
func TestBaseScalarMult(t *testing.T) {
|
||||||
|
var a, b [32]byte
|
||||||
|
in := &a
|
||||||
|
out := &b
|
||||||
|
a[0] = 1
|
||||||
|
|
||||||
|
for i := 0; i < 200; i++ {
|
||||||
|
ScalarBaseMult(out, in)
|
||||||
|
in, out = out, in
|
||||||
|
}
|
||||||
|
|
||||||
|
result := fmt.Sprintf("%x", in[:])
|
||||||
|
if result != expectedHex {
|
||||||
|
t.Errorf("incorrect result: got %s, want %s", result, expectedHex)
|
||||||
|
}
|
||||||
|
}
|
23
vendor/golang.org/x/crypto/curve25519/doc.go
generated
vendored
Normal file
23
vendor/golang.org/x/crypto/curve25519/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package curve25519 provides an implementation of scalar multiplication on
|
||||||
|
// the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html
|
||||||
|
package curve25519 // import "golang.org/x/crypto/curve25519"
|
||||||
|
|
||||||
|
// basePoint is the x coordinate of the generator of the curve.
|
||||||
|
var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
|
||||||
|
// ScalarMult sets dst to the product in*base where dst and base are the x
|
||||||
|
// coordinates of group points and all values are in little-endian form.
|
||||||
|
func ScalarMult(dst, in, base *[32]byte) {
|
||||||
|
scalarMult(dst, in, base)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScalarBaseMult sets dst to the product in*base where dst and base are the x
|
||||||
|
// coordinates of group points, base is the standard generator and all values
|
||||||
|
// are in little-endian form.
|
||||||
|
func ScalarBaseMult(dst, in *[32]byte) {
|
||||||
|
ScalarMult(dst, in, &basePoint)
|
||||||
|
}
|
94
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
generated
vendored
Normal file
94
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
generated
vendored
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This code was translated into a form compatible with 6a from the public
|
||||||
|
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||||
|
|
||||||
|
// +build amd64,!gccgo
|
||||||
|
|
||||||
|
// func freeze(inout *[5]uint64)
|
||||||
|
TEXT ·freeze(SB),7,$96-8
|
||||||
|
MOVQ inout+0(FP), DI
|
||||||
|
|
||||||
|
MOVQ SP,R11
|
||||||
|
MOVQ $31,CX
|
||||||
|
NOTQ CX
|
||||||
|
ANDQ CX,SP
|
||||||
|
ADDQ $32,SP
|
||||||
|
|
||||||
|
MOVQ R11,0(SP)
|
||||||
|
MOVQ R12,8(SP)
|
||||||
|
MOVQ R13,16(SP)
|
||||||
|
MOVQ R14,24(SP)
|
||||||
|
MOVQ R15,32(SP)
|
||||||
|
MOVQ BX,40(SP)
|
||||||
|
MOVQ BP,48(SP)
|
||||||
|
MOVQ 0(DI),SI
|
||||||
|
MOVQ 8(DI),DX
|
||||||
|
MOVQ 16(DI),CX
|
||||||
|
MOVQ 24(DI),R8
|
||||||
|
MOVQ 32(DI),R9
|
||||||
|
MOVQ ·REDMASK51(SB),AX
|
||||||
|
MOVQ AX,R10
|
||||||
|
SUBQ $18,R10
|
||||||
|
MOVQ $3,R11
|
||||||
|
REDUCELOOP:
|
||||||
|
MOVQ SI,R12
|
||||||
|
SHRQ $51,R12
|
||||||
|
ANDQ AX,SI
|
||||||
|
ADDQ R12,DX
|
||||||
|
MOVQ DX,R12
|
||||||
|
SHRQ $51,R12
|
||||||
|
ANDQ AX,DX
|
||||||
|
ADDQ R12,CX
|
||||||
|
MOVQ CX,R12
|
||||||
|
SHRQ $51,R12
|
||||||
|
ANDQ AX,CX
|
||||||
|
ADDQ R12,R8
|
||||||
|
MOVQ R8,R12
|
||||||
|
SHRQ $51,R12
|
||||||
|
ANDQ AX,R8
|
||||||
|
ADDQ R12,R9
|
||||||
|
MOVQ R9,R12
|
||||||
|
SHRQ $51,R12
|
||||||
|
ANDQ AX,R9
|
||||||
|
IMUL3Q $19,R12,R12
|
||||||
|
ADDQ R12,SI
|
||||||
|
SUBQ $1,R11
|
||||||
|
JA REDUCELOOP
|
||||||
|
MOVQ $1,R12
|
||||||
|
CMPQ R10,SI
|
||||||
|
CMOVQLT R11,R12
|
||||||
|
CMPQ AX,DX
|
||||||
|
CMOVQNE R11,R12
|
||||||
|
CMPQ AX,CX
|
||||||
|
CMOVQNE R11,R12
|
||||||
|
CMPQ AX,R8
|
||||||
|
CMOVQNE R11,R12
|
||||||
|
CMPQ AX,R9
|
||||||
|
CMOVQNE R11,R12
|
||||||
|
NEGQ R12
|
||||||
|
ANDQ R12,AX
|
||||||
|
ANDQ R12,R10
|
||||||
|
SUBQ R10,SI
|
||||||
|
SUBQ AX,DX
|
||||||
|
SUBQ AX,CX
|
||||||
|
SUBQ AX,R8
|
||||||
|
SUBQ AX,R9
|
||||||
|
MOVQ SI,0(DI)
|
||||||
|
MOVQ DX,8(DI)
|
||||||
|
MOVQ CX,16(DI)
|
||||||
|
MOVQ R8,24(DI)
|
||||||
|
MOVQ R9,32(DI)
|
||||||
|
MOVQ 0(SP),R11
|
||||||
|
MOVQ 8(SP),R12
|
||||||
|
MOVQ 16(SP),R13
|
||||||
|
MOVQ 24(SP),R14
|
||||||
|
MOVQ 32(SP),R15
|
||||||
|
MOVQ 40(SP),BX
|
||||||
|
MOVQ 48(SP),BP
|
||||||
|
MOVQ R11,SP
|
||||||
|
MOVQ DI,AX
|
||||||
|
MOVQ SI,DX
|
||||||
|
RET
|
1398
vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
generated
vendored
Normal file
1398
vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
240
vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go
generated
vendored
Normal file
240
vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go
generated
vendored
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build amd64,!gccgo
|
||||||
|
|
||||||
|
package curve25519
|
||||||
|
|
||||||
|
// These functions are implemented in the .s files. The names of the functions
|
||||||
|
// in the rest of the file are also taken from the SUPERCOP sources to help
|
||||||
|
// people following along.
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
|
||||||
|
func cswap(inout *[5]uint64, v uint64)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
|
||||||
|
func ladderstep(inout *[5][5]uint64)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
|
||||||
|
func freeze(inout *[5]uint64)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
|
||||||
|
func mul(dest, a, b *[5]uint64)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
|
||||||
|
func square(out, in *[5]uint64)
|
||||||
|
|
||||||
|
// mladder uses a Montgomery ladder to calculate (xr/zr) *= s.
|
||||||
|
func mladder(xr, zr *[5]uint64, s *[32]byte) {
|
||||||
|
var work [5][5]uint64
|
||||||
|
|
||||||
|
work[0] = *xr
|
||||||
|
setint(&work[1], 1)
|
||||||
|
setint(&work[2], 0)
|
||||||
|
work[3] = *xr
|
||||||
|
setint(&work[4], 1)
|
||||||
|
|
||||||
|
j := uint(6)
|
||||||
|
var prevbit byte
|
||||||
|
|
||||||
|
for i := 31; i >= 0; i-- {
|
||||||
|
for j < 8 {
|
||||||
|
bit := ((*s)[i] >> j) & 1
|
||||||
|
swap := bit ^ prevbit
|
||||||
|
prevbit = bit
|
||||||
|
cswap(&work[1], uint64(swap))
|
||||||
|
ladderstep(&work)
|
||||||
|
j--
|
||||||
|
}
|
||||||
|
j = 7
|
||||||
|
}
|
||||||
|
|
||||||
|
*xr = work[1]
|
||||||
|
*zr = work[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
func scalarMult(out, in, base *[32]byte) {
|
||||||
|
var e [32]byte
|
||||||
|
copy(e[:], (*in)[:])
|
||||||
|
e[0] &= 248
|
||||||
|
e[31] &= 127
|
||||||
|
e[31] |= 64
|
||||||
|
|
||||||
|
var t, z [5]uint64
|
||||||
|
unpack(&t, base)
|
||||||
|
mladder(&t, &z, &e)
|
||||||
|
invert(&z, &z)
|
||||||
|
mul(&t, &t, &z)
|
||||||
|
pack(out, &t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setint(r *[5]uint64, v uint64) {
|
||||||
|
r[0] = v
|
||||||
|
r[1] = 0
|
||||||
|
r[2] = 0
|
||||||
|
r[3] = 0
|
||||||
|
r[4] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// unpack sets r = x where r consists of 5, 51-bit limbs in little-endian
|
||||||
|
// order.
|
||||||
|
func unpack(r *[5]uint64, x *[32]byte) {
|
||||||
|
r[0] = uint64(x[0]) |
|
||||||
|
uint64(x[1])<<8 |
|
||||||
|
uint64(x[2])<<16 |
|
||||||
|
uint64(x[3])<<24 |
|
||||||
|
uint64(x[4])<<32 |
|
||||||
|
uint64(x[5])<<40 |
|
||||||
|
uint64(x[6]&7)<<48
|
||||||
|
|
||||||
|
r[1] = uint64(x[6])>>3 |
|
||||||
|
uint64(x[7])<<5 |
|
||||||
|
uint64(x[8])<<13 |
|
||||||
|
uint64(x[9])<<21 |
|
||||||
|
uint64(x[10])<<29 |
|
||||||
|
uint64(x[11])<<37 |
|
||||||
|
uint64(x[12]&63)<<45
|
||||||
|
|
||||||
|
r[2] = uint64(x[12])>>6 |
|
||||||
|
uint64(x[13])<<2 |
|
||||||
|
uint64(x[14])<<10 |
|
||||||
|
uint64(x[15])<<18 |
|
||||||
|
uint64(x[16])<<26 |
|
||||||
|
uint64(x[17])<<34 |
|
||||||
|
uint64(x[18])<<42 |
|
||||||
|
uint64(x[19]&1)<<50
|
||||||
|
|
||||||
|
r[3] = uint64(x[19])>>1 |
|
||||||
|
uint64(x[20])<<7 |
|
||||||
|
uint64(x[21])<<15 |
|
||||||
|
uint64(x[22])<<23 |
|
||||||
|
uint64(x[23])<<31 |
|
||||||
|
uint64(x[24])<<39 |
|
||||||
|
uint64(x[25]&15)<<47
|
||||||
|
|
||||||
|
r[4] = uint64(x[25])>>4 |
|
||||||
|
uint64(x[26])<<4 |
|
||||||
|
uint64(x[27])<<12 |
|
||||||
|
uint64(x[28])<<20 |
|
||||||
|
uint64(x[29])<<28 |
|
||||||
|
uint64(x[30])<<36 |
|
||||||
|
uint64(x[31]&127)<<44
|
||||||
|
}
|
||||||
|
|
||||||
|
// pack sets out = x where out is the usual, little-endian form of the 5,
|
||||||
|
// 51-bit limbs in x.
|
||||||
|
func pack(out *[32]byte, x *[5]uint64) {
|
||||||
|
t := *x
|
||||||
|
freeze(&t)
|
||||||
|
|
||||||
|
out[0] = byte(t[0])
|
||||||
|
out[1] = byte(t[0] >> 8)
|
||||||
|
out[2] = byte(t[0] >> 16)
|
||||||
|
out[3] = byte(t[0] >> 24)
|
||||||
|
out[4] = byte(t[0] >> 32)
|
||||||
|
out[5] = byte(t[0] >> 40)
|
||||||
|
out[6] = byte(t[0] >> 48)
|
||||||
|
|
||||||
|
out[6] ^= byte(t[1]<<3) & 0xf8
|
||||||
|
out[7] = byte(t[1] >> 5)
|
||||||
|
out[8] = byte(t[1] >> 13)
|
||||||
|
out[9] = byte(t[1] >> 21)
|
||||||
|
out[10] = byte(t[1] >> 29)
|
||||||
|
out[11] = byte(t[1] >> 37)
|
||||||
|
out[12] = byte(t[1] >> 45)
|
||||||
|
|
||||||
|
out[12] ^= byte(t[2]<<6) & 0xc0
|
||||||
|
out[13] = byte(t[2] >> 2)
|
||||||
|
out[14] = byte(t[2] >> 10)
|
||||||
|
out[15] = byte(t[2] >> 18)
|
||||||
|
out[16] = byte(t[2] >> 26)
|
||||||
|
out[17] = byte(t[2] >> 34)
|
||||||
|
out[18] = byte(t[2] >> 42)
|
||||||
|
out[19] = byte(t[2] >> 50)
|
||||||
|
|
||||||
|
out[19] ^= byte(t[3]<<1) & 0xfe
|
||||||
|
out[20] = byte(t[3] >> 7)
|
||||||
|
out[21] = byte(t[3] >> 15)
|
||||||
|
out[22] = byte(t[3] >> 23)
|
||||||
|
out[23] = byte(t[3] >> 31)
|
||||||
|
out[24] = byte(t[3] >> 39)
|
||||||
|
out[25] = byte(t[3] >> 47)
|
||||||
|
|
||||||
|
out[25] ^= byte(t[4]<<4) & 0xf0
|
||||||
|
out[26] = byte(t[4] >> 4)
|
||||||
|
out[27] = byte(t[4] >> 12)
|
||||||
|
out[28] = byte(t[4] >> 20)
|
||||||
|
out[29] = byte(t[4] >> 28)
|
||||||
|
out[30] = byte(t[4] >> 36)
|
||||||
|
out[31] = byte(t[4] >> 44)
|
||||||
|
}
|
||||||
|
|
||||||
|
// invert calculates r = x^-1 mod p using Fermat's little theorem.
|
||||||
|
func invert(r *[5]uint64, x *[5]uint64) {
|
||||||
|
var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64
|
||||||
|
|
||||||
|
square(&z2, x) /* 2 */
|
||||||
|
square(&t, &z2) /* 4 */
|
||||||
|
square(&t, &t) /* 8 */
|
||||||
|
mul(&z9, &t, x) /* 9 */
|
||||||
|
mul(&z11, &z9, &z2) /* 11 */
|
||||||
|
square(&t, &z11) /* 22 */
|
||||||
|
mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */
|
||||||
|
|
||||||
|
square(&t, &z2_5_0) /* 2^6 - 2^1 */
|
||||||
|
for i := 1; i < 5; i++ { /* 2^20 - 2^10 */
|
||||||
|
square(&t, &t)
|
||||||
|
}
|
||||||
|
mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */
|
||||||
|
|
||||||
|
square(&t, &z2_10_0) /* 2^11 - 2^1 */
|
||||||
|
for i := 1; i < 10; i++ { /* 2^20 - 2^10 */
|
||||||
|
square(&t, &t)
|
||||||
|
}
|
||||||
|
mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */
|
||||||
|
|
||||||
|
square(&t, &z2_20_0) /* 2^21 - 2^1 */
|
||||||
|
for i := 1; i < 20; i++ { /* 2^40 - 2^20 */
|
||||||
|
square(&t, &t)
|
||||||
|
}
|
||||||
|
mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */
|
||||||
|
|
||||||
|
square(&t, &t) /* 2^41 - 2^1 */
|
||||||
|
for i := 1; i < 10; i++ { /* 2^50 - 2^10 */
|
||||||
|
square(&t, &t)
|
||||||
|
}
|
||||||
|
mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */
|
||||||
|
|
||||||
|
square(&t, &z2_50_0) /* 2^51 - 2^1 */
|
||||||
|
for i := 1; i < 50; i++ { /* 2^100 - 2^50 */
|
||||||
|
square(&t, &t)
|
||||||
|
}
|
||||||
|
mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */
|
||||||
|
|
||||||
|
square(&t, &z2_100_0) /* 2^101 - 2^1 */
|
||||||
|
for i := 1; i < 100; i++ { /* 2^200 - 2^100 */
|
||||||
|
square(&t, &t)
|
||||||
|
}
|
||||||
|
mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */
|
||||||
|
|
||||||
|
square(&t, &t) /* 2^201 - 2^1 */
|
||||||
|
for i := 1; i < 50; i++ { /* 2^250 - 2^50 */
|
||||||
|
square(&t, &t)
|
||||||
|
}
|
||||||
|
mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */
|
||||||
|
|
||||||
|
square(&t, &t) /* 2^251 - 2^1 */
|
||||||
|
square(&t, &t) /* 2^252 - 2^2 */
|
||||||
|
square(&t, &t) /* 2^253 - 2^3 */
|
||||||
|
|
||||||
|
square(&t, &t) /* 2^254 - 2^4 */
|
||||||
|
|
||||||
|
square(&t, &t) /* 2^255 - 2^5 */
|
||||||
|
mul(r, &t, &z11) /* 2^255 - 21 */
|
||||||
|
}
|
191
vendor/golang.org/x/crypto/curve25519/mul_amd64.s
generated
vendored
Normal file
191
vendor/golang.org/x/crypto/curve25519/mul_amd64.s
generated
vendored
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This code was translated into a form compatible with 6a from the public
|
||||||
|
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||||
|
|
||||||
|
// +build amd64,!gccgo
|
||||||
|
|
||||||
|
// func mul(dest, a, b *[5]uint64)
|
||||||
|
TEXT ·mul(SB),0,$128-24
|
||||||
|
MOVQ dest+0(FP), DI
|
||||||
|
MOVQ a+8(FP), SI
|
||||||
|
MOVQ b+16(FP), DX
|
||||||
|
|
||||||
|
MOVQ SP,R11
|
||||||
|
MOVQ $31,CX
|
||||||
|
NOTQ CX
|
||||||
|
ANDQ CX,SP
|
||||||
|
ADDQ $32,SP
|
||||||
|
|
||||||
|
MOVQ R11,0(SP)
|
||||||
|
MOVQ R12,8(SP)
|
||||||
|
MOVQ R13,16(SP)
|
||||||
|
MOVQ R14,24(SP)
|
||||||
|
MOVQ R15,32(SP)
|
||||||
|
MOVQ BX,40(SP)
|
||||||
|
MOVQ BP,48(SP)
|
||||||
|
MOVQ DI,56(SP)
|
||||||
|
MOVQ DX,CX
|
||||||
|
MOVQ 24(SI),DX
|
||||||
|
IMUL3Q $19,DX,AX
|
||||||
|
MOVQ AX,64(SP)
|
||||||
|
MULQ 16(CX)
|
||||||
|
MOVQ AX,R8
|
||||||
|
MOVQ DX,R9
|
||||||
|
MOVQ 32(SI),DX
|
||||||
|
IMUL3Q $19,DX,AX
|
||||||
|
MOVQ AX,72(SP)
|
||||||
|
MULQ 8(CX)
|
||||||
|
ADDQ AX,R8
|
||||||
|
ADCQ DX,R9
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
MULQ 0(CX)
|
||||||
|
ADDQ AX,R8
|
||||||
|
ADCQ DX,R9
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
MULQ 8(CX)
|
||||||
|
MOVQ AX,R10
|
||||||
|
MOVQ DX,R11
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
MULQ 16(CX)
|
||||||
|
MOVQ AX,R12
|
||||||
|
MOVQ DX,R13
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
MULQ 24(CX)
|
||||||
|
MOVQ AX,R14
|
||||||
|
MOVQ DX,R15
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
MOVQ AX,BX
|
||||||
|
MOVQ DX,BP
|
||||||
|
MOVQ 8(SI),AX
|
||||||
|
MULQ 0(CX)
|
||||||
|
ADDQ AX,R10
|
||||||
|
ADCQ DX,R11
|
||||||
|
MOVQ 8(SI),AX
|
||||||
|
MULQ 8(CX)
|
||||||
|
ADDQ AX,R12
|
||||||
|
ADCQ DX,R13
|
||||||
|
MOVQ 8(SI),AX
|
||||||
|
MULQ 16(CX)
|
||||||
|
ADDQ AX,R14
|
||||||
|
ADCQ DX,R15
|
||||||
|
MOVQ 8(SI),AX
|
||||||
|
MULQ 24(CX)
|
||||||
|
ADDQ AX,BX
|
||||||
|
ADCQ DX,BP
|
||||||
|
MOVQ 8(SI),DX
|
||||||
|
IMUL3Q $19,DX,AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
ADDQ AX,R8
|
||||||
|
ADCQ DX,R9
|
||||||
|
MOVQ 16(SI),AX
|
||||||
|
MULQ 0(CX)
|
||||||
|
ADDQ AX,R12
|
||||||
|
ADCQ DX,R13
|
||||||
|
MOVQ 16(SI),AX
|
||||||
|
MULQ 8(CX)
|
||||||
|
ADDQ AX,R14
|
||||||
|
ADCQ DX,R15
|
||||||
|
MOVQ 16(SI),AX
|
||||||
|
MULQ 16(CX)
|
||||||
|
ADDQ AX,BX
|
||||||
|
ADCQ DX,BP
|
||||||
|
MOVQ 16(SI),DX
|
||||||
|
IMUL3Q $19,DX,AX
|
||||||
|
MULQ 24(CX)
|
||||||
|
ADDQ AX,R8
|
||||||
|
ADCQ DX,R9
|
||||||
|
MOVQ 16(SI),DX
|
||||||
|
IMUL3Q $19,DX,AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
ADDQ AX,R10
|
||||||
|
ADCQ DX,R11
|
||||||
|
MOVQ 24(SI),AX
|
||||||
|
MULQ 0(CX)
|
||||||
|
ADDQ AX,R14
|
||||||
|
ADCQ DX,R15
|
||||||
|
MOVQ 24(SI),AX
|
||||||
|
MULQ 8(CX)
|
||||||
|
ADDQ AX,BX
|
||||||
|
ADCQ DX,BP
|
||||||
|
MOVQ 64(SP),AX
|
||||||
|
MULQ 24(CX)
|
||||||
|
ADDQ AX,R10
|
||||||
|
ADCQ DX,R11
|
||||||
|
MOVQ 64(SP),AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
ADDQ AX,R12
|
||||||
|
ADCQ DX,R13
|
||||||
|
MOVQ 32(SI),AX
|
||||||
|
MULQ 0(CX)
|
||||||
|
ADDQ AX,BX
|
||||||
|
ADCQ DX,BP
|
||||||
|
MOVQ 72(SP),AX
|
||||||
|
MULQ 16(CX)
|
||||||
|
ADDQ AX,R10
|
||||||
|
ADCQ DX,R11
|
||||||
|
MOVQ 72(SP),AX
|
||||||
|
MULQ 24(CX)
|
||||||
|
ADDQ AX,R12
|
||||||
|
ADCQ DX,R13
|
||||||
|
MOVQ 72(SP),AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
ADDQ AX,R14
|
||||||
|
ADCQ DX,R15
|
||||||
|
MOVQ ·REDMASK51(SB),SI
|
||||||
|
SHLQ $13,R9:R8
|
||||||
|
ANDQ SI,R8
|
||||||
|
SHLQ $13,R11:R10
|
||||||
|
ANDQ SI,R10
|
||||||
|
ADDQ R9,R10
|
||||||
|
SHLQ $13,R13:R12
|
||||||
|
ANDQ SI,R12
|
||||||
|
ADDQ R11,R12
|
||||||
|
SHLQ $13,R15:R14
|
||||||
|
ANDQ SI,R14
|
||||||
|
ADDQ R13,R14
|
||||||
|
SHLQ $13,BP:BX
|
||||||
|
ANDQ SI,BX
|
||||||
|
ADDQ R15,BX
|
||||||
|
IMUL3Q $19,BP,DX
|
||||||
|
ADDQ DX,R8
|
||||||
|
MOVQ R8,DX
|
||||||
|
SHRQ $51,DX
|
||||||
|
ADDQ R10,DX
|
||||||
|
MOVQ DX,CX
|
||||||
|
SHRQ $51,DX
|
||||||
|
ANDQ SI,R8
|
||||||
|
ADDQ R12,DX
|
||||||
|
MOVQ DX,R9
|
||||||
|
SHRQ $51,DX
|
||||||
|
ANDQ SI,CX
|
||||||
|
ADDQ R14,DX
|
||||||
|
MOVQ DX,AX
|
||||||
|
SHRQ $51,DX
|
||||||
|
ANDQ SI,R9
|
||||||
|
ADDQ BX,DX
|
||||||
|
MOVQ DX,R10
|
||||||
|
SHRQ $51,DX
|
||||||
|
ANDQ SI,AX
|
||||||
|
IMUL3Q $19,DX,DX
|
||||||
|
ADDQ DX,R8
|
||||||
|
ANDQ SI,R10
|
||||||
|
MOVQ R8,0(DI)
|
||||||
|
MOVQ CX,8(DI)
|
||||||
|
MOVQ R9,16(DI)
|
||||||
|
MOVQ AX,24(DI)
|
||||||
|
MOVQ R10,32(DI)
|
||||||
|
MOVQ 0(SP),R11
|
||||||
|
MOVQ 8(SP),R12
|
||||||
|
MOVQ 16(SP),R13
|
||||||
|
MOVQ 24(SP),R14
|
||||||
|
MOVQ 32(SP),R15
|
||||||
|
MOVQ 40(SP),BX
|
||||||
|
MOVQ 48(SP),BP
|
||||||
|
MOVQ R11,SP
|
||||||
|
MOVQ DI,AX
|
||||||
|
MOVQ SI,DX
|
||||||
|
RET
|
153
vendor/golang.org/x/crypto/curve25519/square_amd64.s
generated
vendored
Normal file
153
vendor/golang.org/x/crypto/curve25519/square_amd64.s
generated
vendored
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This code was translated into a form compatible with 6a from the public
|
||||||
|
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||||
|
|
||||||
|
// +build amd64,!gccgo
|
||||||
|
|
||||||
|
// func square(out, in *[5]uint64)
|
||||||
|
TEXT ·square(SB),7,$96-16
|
||||||
|
MOVQ out+0(FP), DI
|
||||||
|
MOVQ in+8(FP), SI
|
||||||
|
|
||||||
|
MOVQ SP,R11
|
||||||
|
MOVQ $31,CX
|
||||||
|
NOTQ CX
|
||||||
|
ANDQ CX,SP
|
||||||
|
ADDQ $32, SP
|
||||||
|
|
||||||
|
MOVQ R11,0(SP)
|
||||||
|
MOVQ R12,8(SP)
|
||||||
|
MOVQ R13,16(SP)
|
||||||
|
MOVQ R14,24(SP)
|
||||||
|
MOVQ R15,32(SP)
|
||||||
|
MOVQ BX,40(SP)
|
||||||
|
MOVQ BP,48(SP)
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
MULQ 0(SI)
|
||||||
|
MOVQ AX,CX
|
||||||
|
MOVQ DX,R8
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
SHLQ $1,AX
|
||||||
|
MULQ 8(SI)
|
||||||
|
MOVQ AX,R9
|
||||||
|
MOVQ DX,R10
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
SHLQ $1,AX
|
||||||
|
MULQ 16(SI)
|
||||||
|
MOVQ AX,R11
|
||||||
|
MOVQ DX,R12
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
SHLQ $1,AX
|
||||||
|
MULQ 24(SI)
|
||||||
|
MOVQ AX,R13
|
||||||
|
MOVQ DX,R14
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
SHLQ $1,AX
|
||||||
|
MULQ 32(SI)
|
||||||
|
MOVQ AX,R15
|
||||||
|
MOVQ DX,BX
|
||||||
|
MOVQ 8(SI),AX
|
||||||
|
MULQ 8(SI)
|
||||||
|
ADDQ AX,R11
|
||||||
|
ADCQ DX,R12
|
||||||
|
MOVQ 8(SI),AX
|
||||||
|
SHLQ $1,AX
|
||||||
|
MULQ 16(SI)
|
||||||
|
ADDQ AX,R13
|
||||||
|
ADCQ DX,R14
|
||||||
|
MOVQ 8(SI),AX
|
||||||
|
SHLQ $1,AX
|
||||||
|
MULQ 24(SI)
|
||||||
|
ADDQ AX,R15
|
||||||
|
ADCQ DX,BX
|
||||||
|
MOVQ 8(SI),DX
|
||||||
|
IMUL3Q $38,DX,AX
|
||||||
|
MULQ 32(SI)
|
||||||
|
ADDQ AX,CX
|
||||||
|
ADCQ DX,R8
|
||||||
|
MOVQ 16(SI),AX
|
||||||
|
MULQ 16(SI)
|
||||||
|
ADDQ AX,R15
|
||||||
|
ADCQ DX,BX
|
||||||
|
MOVQ 16(SI),DX
|
||||||
|
IMUL3Q $38,DX,AX
|
||||||
|
MULQ 24(SI)
|
||||||
|
ADDQ AX,CX
|
||||||
|
ADCQ DX,R8
|
||||||
|
MOVQ 16(SI),DX
|
||||||
|
IMUL3Q $38,DX,AX
|
||||||
|
MULQ 32(SI)
|
||||||
|
ADDQ AX,R9
|
||||||
|
ADCQ DX,R10
|
||||||
|
MOVQ 24(SI),DX
|
||||||
|
IMUL3Q $19,DX,AX
|
||||||
|
MULQ 24(SI)
|
||||||
|
ADDQ AX,R9
|
||||||
|
ADCQ DX,R10
|
||||||
|
MOVQ 24(SI),DX
|
||||||
|
IMUL3Q $38,DX,AX
|
||||||
|
MULQ 32(SI)
|
||||||
|
ADDQ AX,R11
|
||||||
|
ADCQ DX,R12
|
||||||
|
MOVQ 32(SI),DX
|
||||||
|
IMUL3Q $19,DX,AX
|
||||||
|
MULQ 32(SI)
|
||||||
|
ADDQ AX,R13
|
||||||
|
ADCQ DX,R14
|
||||||
|
MOVQ ·REDMASK51(SB),SI
|
||||||
|
SHLQ $13,R8:CX
|
||||||
|
ANDQ SI,CX
|
||||||
|
SHLQ $13,R10:R9
|
||||||
|
ANDQ SI,R9
|
||||||
|
ADDQ R8,R9
|
||||||
|
SHLQ $13,R12:R11
|
||||||
|
ANDQ SI,R11
|
||||||
|
ADDQ R10,R11
|
||||||
|
SHLQ $13,R14:R13
|
||||||
|
ANDQ SI,R13
|
||||||
|
ADDQ R12,R13
|
||||||
|
SHLQ $13,BX:R15
|
||||||
|
ANDQ SI,R15
|
||||||
|
ADDQ R14,R15
|
||||||
|
IMUL3Q $19,BX,DX
|
||||||
|
ADDQ DX,CX
|
||||||
|
MOVQ CX,DX
|
||||||
|
SHRQ $51,DX
|
||||||
|
ADDQ R9,DX
|
||||||
|
ANDQ SI,CX
|
||||||
|
MOVQ DX,R8
|
||||||
|
SHRQ $51,DX
|
||||||
|
ADDQ R11,DX
|
||||||
|
ANDQ SI,R8
|
||||||
|
MOVQ DX,R9
|
||||||
|
SHRQ $51,DX
|
||||||
|
ADDQ R13,DX
|
||||||
|
ANDQ SI,R9
|
||||||
|
MOVQ DX,AX
|
||||||
|
SHRQ $51,DX
|
||||||
|
ADDQ R15,DX
|
||||||
|
ANDQ SI,AX
|
||||||
|
MOVQ DX,R10
|
||||||
|
SHRQ $51,DX
|
||||||
|
IMUL3Q $19,DX,DX
|
||||||
|
ADDQ DX,CX
|
||||||
|
ANDQ SI,R10
|
||||||
|
MOVQ CX,0(DI)
|
||||||
|
MOVQ R8,8(DI)
|
||||||
|
MOVQ R9,16(DI)
|
||||||
|
MOVQ AX,24(DI)
|
||||||
|
MOVQ R10,32(DI)
|
||||||
|
MOVQ 0(SP),R11
|
||||||
|
MOVQ 8(SP),R12
|
||||||
|
MOVQ 16(SP),R13
|
||||||
|
MOVQ 24(SP),R14
|
||||||
|
MOVQ 32(SP),R15
|
||||||
|
MOVQ 40(SP),BX
|
||||||
|
MOVQ 48(SP),BP
|
||||||
|
MOVQ R11,SP
|
||||||
|
MOVQ DI,AX
|
||||||
|
MOVQ SI,DX
|
||||||
|
RET
|
61
vendor/golang.org/x/crypto/hkdf/example_test.go
generated
vendored
Normal file
61
vendor/golang.org/x/crypto/hkdf/example_test.go
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package hkdf_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/crypto/hkdf"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Usage example that expands one master key into three other cryptographically
|
||||||
|
// secure keys.
|
||||||
|
func Example_usage() {
|
||||||
|
// Underlying hash function to use
|
||||||
|
hash := sha256.New
|
||||||
|
|
||||||
|
// Cryptographically secure master key.
|
||||||
|
master := []byte{0x00, 0x01, 0x02, 0x03} // i.e. NOT this.
|
||||||
|
|
||||||
|
// Non secret salt, optional (can be nil)
|
||||||
|
// Recommended: hash-length sized random
|
||||||
|
salt := make([]byte, hash().Size())
|
||||||
|
n, err := io.ReadFull(rand.Reader, salt)
|
||||||
|
if n != len(salt) || err != nil {
|
||||||
|
fmt.Println("error:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non secret context specific info, optional (can be nil).
|
||||||
|
// Note, independent from the master key.
|
||||||
|
info := []byte{0x03, 0x14, 0x15, 0x92, 0x65}
|
||||||
|
|
||||||
|
// Create the key derivation function
|
||||||
|
hkdf := hkdf.New(hash, master, salt, info)
|
||||||
|
|
||||||
|
// Generate the required keys
|
||||||
|
keys := make([][]byte, 3)
|
||||||
|
for i := 0; i < len(keys); i++ {
|
||||||
|
keys[i] = make([]byte, 24)
|
||||||
|
n, err := io.ReadFull(hkdf, keys[i])
|
||||||
|
if n != len(keys[i]) || err != nil {
|
||||||
|
fmt.Println("error:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys should contain 192 bit random keys
|
||||||
|
for i := 1; i <= len(keys); i++ {
|
||||||
|
fmt.Printf("Key #%d: %v\n", i, !bytes.Equal(keys[i-1], make([]byte, 24)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Key #1: true
|
||||||
|
// Key #2: true
|
||||||
|
// Key #3: true
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue